...

Source file src/pkg/cmd/go/internal/sumweb/test.go

     1	// Copyright 2019 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	
     5	package sumweb
     6	
     7	import (
     8		"context"
     9		"fmt"
    10		"net/http"
    11		"strings"
    12		"sync"
    13	
    14		"cmd/go/internal/note"
    15		"cmd/go/internal/tlog"
    16	)
    17	
    18	// NewTestServer constructs a new TestServer
    19	// that will sign its tree with the given signer key
    20	// (see cmd/go/internal/note)
    21	// and fetch new records as needed by calling gosum.
    22	func NewTestServer(signer string, gosum func(path, vers string) ([]byte, error)) *TestServer {
    23		return &TestServer{signer: signer, gosum: gosum}
    24	}
    25	
    26	// A TestServer is an in-memory implementation of Server for testing.
    27	type TestServer struct {
    28		signer string
    29		gosum  func(path, vers string) ([]byte, error)
    30	
    31		mu      sync.Mutex
    32		hashes  testHashes
    33		records [][]byte
    34		lookup  map[string]int64
    35	}
    36	
    37	// testHashes implements tlog.HashReader, reading from a slice.
    38	type testHashes []tlog.Hash
    39	
    40	func (h testHashes) ReadHashes(indexes []int64) ([]tlog.Hash, error) {
    41		var list []tlog.Hash
    42		for _, id := range indexes {
    43			list = append(list, h[id])
    44		}
    45		return list, nil
    46	}
    47	
    48	func (s *TestServer) NewContext(r *http.Request) (context.Context, error) {
    49		return nil, nil
    50	}
    51	
    52	func (s *TestServer) Signed(ctx context.Context) ([]byte, error) {
    53		s.mu.Lock()
    54		defer s.mu.Unlock()
    55	
    56		size := int64(len(s.records))
    57		h, err := tlog.TreeHash(size, s.hashes)
    58		if err != nil {
    59			return nil, err
    60		}
    61		text := tlog.FormatTree(tlog.Tree{N: size, Hash: h})
    62		signer, err := note.NewSigner(s.signer)
    63		if err != nil {
    64			return nil, err
    65		}
    66		return note.Sign(&note.Note{Text: string(text)}, signer)
    67	}
    68	
    69	func (s *TestServer) ReadRecords(ctx context.Context, id, n int64) ([][]byte, error) {
    70		s.mu.Lock()
    71		defer s.mu.Unlock()
    72	
    73		var list [][]byte
    74		for i := int64(0); i < n; i++ {
    75			if id+i >= int64(len(s.records)) {
    76				return nil, fmt.Errorf("missing records")
    77			}
    78			list = append(list, s.records[id+i])
    79		}
    80		return list, nil
    81	}
    82	
    83	func (s *TestServer) Lookup(ctx context.Context, key string) (int64, error) {
    84		s.mu.Lock()
    85		id, ok := s.lookup[key]
    86		s.mu.Unlock()
    87		if ok {
    88			return id, nil
    89		}
    90	
    91		// Look up module and compute go.sum lines.
    92		i := strings.Index(key, "@")
    93		if i < 0 {
    94			return 0, fmt.Errorf("invalid lookup key %q", key)
    95		}
    96		path, vers := key[:i], key[i+1:]
    97		data, err := s.gosum(path, vers)
    98		if err != nil {
    99			return 0, err
   100		}
   101	
   102		s.mu.Lock()
   103		defer s.mu.Unlock()
   104	
   105		// We ran the fetch without the lock.
   106		// If another fetch happened and committed, use it instead.
   107		id, ok = s.lookup[key]
   108		if ok {
   109			return id, nil
   110		}
   111	
   112		// Add record.
   113		id = int64(len(s.records))
   114		s.records = append(s.records, data)
   115		if s.lookup == nil {
   116			s.lookup = make(map[string]int64)
   117		}
   118		s.lookup[key] = id
   119		hashes, err := tlog.StoredHashesForRecordHash(id, tlog.RecordHash([]byte(data)), s.hashes)
   120		if err != nil {
   121			panic(err)
   122		}
   123		s.hashes = append(s.hashes, hashes...)
   124	
   125		return id, nil
   126	}
   127	
   128	func (s *TestServer) ReadTileData(ctx context.Context, t tlog.Tile) ([]byte, error) {
   129		s.mu.Lock()
   130		defer s.mu.Unlock()
   131	
   132		return tlog.ReadTileData(t, s.hashes)
   133	}
   134	

View as plain text