1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package fixchain
16
17 import (
18 "context"
19 "net/http"
20 "sync"
21 "testing"
22
23 "github.com/google/certificate-transparency-go/client"
24 "github.com/google/certificate-transparency-go/jsonclient"
25 )
26
27
28 func TestNewLogger(t *testing.T) {
29 ctx := context.Background()
30
31 for i, test := range postTests {
32 errors := make(chan *FixError)
33 var wg sync.WaitGroup
34 wg.Add(1)
35 go func() {
36 defer wg.Done()
37 testErrors(t, i, test.expectedErrs, errors)
38 }()
39
40 c := &http.Client{Transport: &postTestRoundTripper{t: t, test: &test, testIndex: i}}
41 logClient, err := client.New(test.url, c, jsonclient.Options{})
42 if err != nil {
43 t.Fatalf("failed to create LogClient: %v", err)
44 }
45 l := NewLogger(ctx, 1, errors, logClient, newNilLimiter(), false)
46
47 l.QueueChain(extractTestChain(t, i, test.chain))
48 l.Wait()
49
50 close(l.errors)
51 wg.Wait()
52
53
54 if test.chain != nil {
55 if test.ferr.Type == None && !l.postCertCache.get(hash(GetTestCertificateFromPEM(t, test.chain[0]))) {
56 t.Errorf("#%d: leaf certificate not cached", i)
57 }
58 if !l.postChainCache.get(hashChain(extractTestChain(t, i, test.chain))) {
59 t.Errorf("#%d: chain not cached", i)
60 }
61 }
62 }
63 }
64
65
66 func TestNewLoggerCaching(t *testing.T) {
67
68 ctx := context.Background()
69 newLoggerTest := struct {
70 url string
71 chains [][]string
72 expectedErrs []errorType
73 }{
74 "https://ct.googleapis.com/pilot",
75 [][]string{
76 {googleLeaf, thawteIntermediate, verisignRoot},
77 {googleLeaf, thawteIntermediate, verisignRoot},
78 {googleLeaf, thawteIntermediate},
79 {testLeaf, testIntermediate2, testIntermediate1, testRoot},
80 },
81 []errorType{},
82 }
83
84 errors := make(chan *FixError)
85 var wg sync.WaitGroup
86 wg.Add(1)
87 go func() {
88 defer wg.Done()
89 testErrors(t, 0, newLoggerTest.expectedErrs, errors)
90 }()
91
92 c := &http.Client{Transport: &newLoggerTestRoundTripper{}}
93 logClient, err := client.New(newLoggerTest.url, c, jsonclient.Options{})
94 if err != nil {
95 t.Fatalf("failed to create LogClient: %v", err)
96 }
97 l := NewLogger(ctx, 5, errors, logClient, newNilLimiter(), false)
98
99 for _, chain := range newLoggerTest.chains {
100 l.QueueChain(extractTestChain(t, 0, chain))
101 }
102 l.Wait()
103 close(l.errors)
104 wg.Wait()
105
106
107 seen := make(map[[hashSize]byte]bool)
108 for i, chain := range newLoggerTest.chains {
109 leafHash := hash(GetTestCertificateFromPEM(t, chain[0]))
110 if !l.postCertCache.get(leafHash) {
111 t.Errorf("Chain %d: leaf certificate not cached", i)
112 }
113 if !seen[leafHash] && !l.postChainCache.get(hashChain(extractTestChain(t, 0, chain))) {
114 t.Errorf("Chain %d: chain not cached", i)
115 }
116 seen[leafHash] = true
117 }
118 }
119
120
121 func TestPostServer(t *testing.T) {
122 ctx := context.Background()
123 for i, test := range postTests {
124 errors := make(chan *FixError)
125 c := &http.Client{Transport: &postTestRoundTripper{t: t, test: &test, testIndex: i}}
126 logClient, err := client.New(test.url, c, jsonclient.Options{})
127 if err != nil {
128 t.Fatalf("failed to create LogClient: %v", err)
129 }
130 l := &Logger{
131 ctx: ctx,
132 client: logClient,
133 toPost: make(chan *toPost),
134 errors: errors,
135 limiter: newNilLimiter(),
136 postCertCache: newLockedMap(),
137 postChainCache: newLockedMap(),
138 }
139 var wg sync.WaitGroup
140 wg.Add(1)
141 go func() {
142 defer wg.Done()
143 testErrors(t, i, test.expectedErrs, errors)
144 }()
145
146 go l.postServer()
147 l.QueueChain(extractTestChain(t, i, test.chain))
148 l.Wait()
149
150 close(l.errors)
151 wg.Wait()
152 }
153 }
154
155
156 func TestIsPosted(t *testing.T) {
157 isPostedTests := []struct {
158 cert string
159 expected bool
160 }{
161 {
162 googleLeaf,
163 true,
164 },
165 {
166 megaLeaf,
167 true,
168 },
169 {
170 testLeaf,
171 false,
172 },
173 {
174 testC,
175 false,
176 },
177 }
178
179 l := &Logger{postCertCache: newLockedMap()}
180 l.postCertCache.set(hash(GetTestCertificateFromPEM(t, googleLeaf)), true)
181 l.postCertCache.set(hash(GetTestCertificateFromPEM(t, megaLeaf)), true)
182 l.postCertCache.set(hash(GetTestCertificateFromPEM(t, testLeaf)), false)
183
184 for i, test := range isPostedTests {
185 if l.IsPosted(GetTestCertificateFromPEM(t, test.cert)) != test.expected {
186 t.Errorf("#%d: received %t, expected %t", i, !test.expected, test.expected)
187 }
188 }
189 }
190
191
192 type loggerQueueTest struct {
193 chain []string
194 expectedChain []string
195 }
196
197 var loggerQueueTests = []loggerQueueTest{
198 {
199 chain: []string{googleLeaf, thawteIntermediate, verisignRoot},
200 expectedChain: []string{"Google", "Thawte", "VeriSign"},
201 },
202 {
203
204 chain: []string{googleLeaf, thawteIntermediate, verisignRoot},
205 },
206 }
207
208 func testLoggerQueueChain(t *testing.T, i int, qt *loggerQueueTest, l *Logger) {
209 defer l.wg.Done()
210 if qt.expectedChain != nil {
211 post := <-l.toPost
212 matchTestChain(t, i, qt.expectedChain, post.chain)
213 l.wg.Done()
214 }
215 }
216
217 func TestLoggerQueueChain(t *testing.T) {
218 ch := make(chan *toPost)
219 defer close(ch)
220 l := &Logger{toPost: ch, postCertCache: newLockedMap(), postChainCache: newLockedMap()}
221
222 for i, qt := range loggerQueueTests {
223 l.wg.Add(1)
224 go testLoggerQueueChain(t, i, &qt, l)
225 chain := extractTestChain(t, i, qt.chain)
226 l.QueueChain(chain)
227 l.wg.Wait()
228 }
229 }
230
231
232 func TestRootCerts(t *testing.T) {
233 ctx := context.Background()
234 rootCertsTests := []struct {
235 url string
236 expectedRoots []string
237 }{
238 {
239 "https://ct.googleapis.com/pilot",
240 []string{verisignRoot, comodoRoot},
241 },
242 }
243
244 for i, test := range rootCertsTests {
245 c := &http.Client{Transport: &rootCertsTestRoundTripper{}}
246 logClient, err := client.New(test.url, c, jsonclient.Options{})
247 if err != nil {
248 t.Fatalf("failed to create LogClient: %v", err)
249 }
250 l := &Logger{ctx: ctx, client: logClient}
251 roots := l.RootCerts()
252 matchTestRoots(t, i, test.expectedRoots, roots)
253 }
254 }
255
View as plain text