• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package x509
6
7import (
8	"testing"
9)
10
11func TestFallbackPanic(t *testing.T) {
12	defer func() {
13		if recover() == nil {
14			t.Fatal("Multiple calls to SetFallbackRoots should panic")
15		}
16	}()
17	SetFallbackRoots(nil)
18	SetFallbackRoots(nil)
19}
20
21func TestFallback(t *testing.T) {
22	// call systemRootsPool so that the sync.Once is triggered, and we can
23	// manipulate systemRoots without worrying about our working being overwritten
24	systemRootsPool()
25	if systemRoots != nil {
26		originalSystemRoots := *systemRoots
27		defer func() { systemRoots = &originalSystemRoots }()
28	}
29
30	tests := []struct {
31		name            string
32		systemRoots     *CertPool
33		systemPool      bool
34		poolContent     []*Certificate
35		forceFallback   bool
36		returnsFallback bool
37	}{
38		{
39			name:            "nil systemRoots",
40			returnsFallback: true,
41		},
42		{
43			name:            "empty systemRoots",
44			systemRoots:     NewCertPool(),
45			returnsFallback: true,
46		},
47		{
48			name:        "empty systemRoots system pool",
49			systemRoots: NewCertPool(),
50			systemPool:  true,
51		},
52		{
53			name:        "filled systemRoots system pool",
54			systemRoots: NewCertPool(),
55			poolContent: []*Certificate{{}},
56			systemPool:  true,
57		},
58		{
59			name:        "filled systemRoots",
60			systemRoots: NewCertPool(),
61			poolContent: []*Certificate{{}},
62		},
63		{
64			name:            "filled systemRoots, force fallback",
65			systemRoots:     NewCertPool(),
66			poolContent:     []*Certificate{{}},
67			forceFallback:   true,
68			returnsFallback: true,
69		},
70		{
71			name:            "filled systemRoot system pool, force fallback",
72			systemRoots:     NewCertPool(),
73			poolContent:     []*Certificate{{}},
74			systemPool:      true,
75			forceFallback:   true,
76			returnsFallback: true,
77		},
78	}
79
80	for _, tc := range tests {
81		t.Run(tc.name, func(t *testing.T) {
82			fallbacksSet = false
83			systemRoots = tc.systemRoots
84			if systemRoots != nil {
85				systemRoots.systemPool = tc.systemPool
86			}
87			for _, c := range tc.poolContent {
88				systemRoots.AddCert(c)
89			}
90			if tc.forceFallback {
91				t.Setenv("GODEBUG", "x509usefallbackroots=1")
92			} else {
93				t.Setenv("GODEBUG", "x509usefallbackroots=0")
94			}
95
96			fallbackPool := NewCertPool()
97			SetFallbackRoots(fallbackPool)
98
99			systemPoolIsFallback := systemRoots == fallbackPool
100
101			if tc.returnsFallback && !systemPoolIsFallback {
102				t.Error("systemRoots was not set to fallback pool")
103			} else if !tc.returnsFallback && systemPoolIsFallback {
104				t.Error("systemRoots was set to fallback pool when it shouldn't have been")
105			}
106		})
107	}
108}
109