...

Source file src/github.com/google/certificate-transparency-go/fixchain/logger_test.go

Documentation: github.com/google/certificate-transparency-go/fixchain

     1  // Copyright 2016 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    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  // NewLogger() test
    28  func TestNewLogger(t *testing.T) {
    29  	ctx := context.Background()
    30  	// Test single chain posts.
    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  		// Check logger caching.
    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  // NewLogger() test
    66  func TestNewLoggerCaching(t *testing.T) {
    67  	// Test logging multiple chains by looking at caching.
    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  	// Check logger caching.
   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  // Logger.postServer() test
   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  // Logger.IsPosted() test
   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  // Logger.QueueChain() tests
   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  	{ // Add the same chain a second time to test chain caching.
   203  		// Note that if chain caching isn't working correctly, the test will hang.
   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() // Required as logger wg is incremented internally every time a toPost is added to the queue.
   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  // Logger.RootCerts() test
   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}, // These are not the actual roots for the pilot CT log, this is just for testing purposes.
   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