Source file src/cmd/internal/buildid/buildid_test.go

     1  // Copyright 2017 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 buildid
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/sha256"
    10  	"internal/obscuretestdata"
    11  	"io/ioutil"
    12  	"os"
    13  	"reflect"
    14  	"strings"
    15  	"testing"
    16  )
    17  
    18  const (
    19  	expectedID = "abcdefghijklmnopqrstuvwxyz.1234567890123456789012345678901234567890123456789012345678901234"
    20  	newID      = "bcdefghijklmnopqrstuvwxyza.2345678901234567890123456789012345678901234567890123456789012341"
    21  )
    22  
    23  func TestReadFile(t *testing.T) {
    24  	f, err := ioutil.TempFile("", "buildid-test-")
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	tmp := f.Name()
    29  	defer os.Remove(tmp)
    30  	f.Close()
    31  
    32  	// Use obscured files to prevent Apple’s notarization service from
    33  	// mistaking them as candidates for notarization and rejecting the entire
    34  	// toolchain.
    35  	// See golang.org/issue/34986
    36  	var files = []string{
    37  		"p.a.base64",
    38  		"a.elf.base64",
    39  		"a.macho.base64",
    40  		"a.pe.base64",
    41  	}
    42  
    43  	for _, name := range files {
    44  		f, err := obscuretestdata.DecodeToTempFile("testdata/" + name)
    45  		if err != nil {
    46  			t.Errorf("obscuretestdata.DecodeToTempFile(testdata/%s): %v", name, err)
    47  			continue
    48  		}
    49  		defer os.Remove(f)
    50  		id, err := ReadFile(f)
    51  		if id != expectedID || err != nil {
    52  			t.Errorf("ReadFile(testdata/%s) = %q, %v, want %q, nil", f, id, err, expectedID)
    53  		}
    54  		old := readSize
    55  		readSize = 2048
    56  		id, err = ReadFile(f)
    57  		readSize = old
    58  		if id != expectedID || err != nil {
    59  			t.Errorf("ReadFile(%s) [readSize=2k] = %q, %v, want %q, nil", f, id, err, expectedID)
    60  		}
    61  
    62  		data, err := ioutil.ReadFile(f)
    63  		if err != nil {
    64  			t.Fatal(err)
    65  		}
    66  		m, _, err := FindAndHash(bytes.NewReader(data), expectedID, 1024)
    67  		if err != nil {
    68  			t.Errorf("FindAndHash(%s): %v", f, err)
    69  			continue
    70  		}
    71  		if err := ioutil.WriteFile(tmp, data, 0666); err != nil {
    72  			t.Error(err)
    73  			continue
    74  		}
    75  		tf, err := os.OpenFile(tmp, os.O_WRONLY, 0)
    76  		if err != nil {
    77  			t.Error(err)
    78  			continue
    79  		}
    80  		err = Rewrite(tf, m, newID)
    81  		err2 := tf.Close()
    82  		if err != nil {
    83  			t.Errorf("Rewrite(%s): %v", f, err)
    84  			continue
    85  		}
    86  		if err2 != nil {
    87  			t.Fatal(err2)
    88  		}
    89  
    90  		id, err = ReadFile(tmp)
    91  		if id != newID || err != nil {
    92  			t.Errorf("ReadFile(%s after Rewrite) = %q, %v, want %q, nil", f, id, err, newID)
    93  		}
    94  	}
    95  }
    96  
    97  func TestFindAndHash(t *testing.T) {
    98  	buf := make([]byte, 64)
    99  	buf2 := make([]byte, 64)
   100  	id := make([]byte, 8)
   101  	zero := make([]byte, 8)
   102  	for i := range id {
   103  		id[i] = byte(i)
   104  	}
   105  	numError := 0
   106  	errorf := func(msg string, args ...any) {
   107  		t.Errorf(msg, args...)
   108  		if numError++; numError > 20 {
   109  			t.Logf("stopping after too many errors")
   110  			t.FailNow()
   111  		}
   112  	}
   113  	for bufSize := len(id); bufSize <= len(buf); bufSize++ {
   114  		for j := range buf {
   115  			for k := 0; k < 2*len(id) && j+k < len(buf); k++ {
   116  				for i := range buf {
   117  					buf[i] = 1
   118  				}
   119  				copy(buf[j:], id)
   120  				copy(buf[j+k:], id)
   121  				var m []int64
   122  				if j+len(id) <= j+k {
   123  					m = append(m, int64(j))
   124  				}
   125  				if j+k+len(id) <= len(buf) {
   126  					m = append(m, int64(j+k))
   127  				}
   128  				copy(buf2, buf)
   129  				for _, p := range m {
   130  					copy(buf2[p:], zero)
   131  				}
   132  				h := sha256.Sum256(buf2)
   133  
   134  				matches, hash, err := FindAndHash(bytes.NewReader(buf), string(id), bufSize)
   135  				if err != nil {
   136  					errorf("bufSize=%d j=%d k=%d: findAndHash: %v", bufSize, j, k, err)
   137  					continue
   138  				}
   139  				if !reflect.DeepEqual(matches, m) {
   140  					errorf("bufSize=%d j=%d k=%d: findAndHash: matches=%v, want %v", bufSize, j, k, matches, m)
   141  					continue
   142  				}
   143  				if hash != h {
   144  					errorf("bufSize=%d j=%d k=%d: findAndHash: matches correct, but hash=%x, want %x", bufSize, j, k, hash, h)
   145  				}
   146  			}
   147  		}
   148  	}
   149  }
   150  
   151  func TestExcludedReader(t *testing.T) {
   152  	const s = "0123456789abcdefghijklmn"
   153  	tests := []struct {
   154  		start, end int64    // excluded range
   155  		results    []string // expected results of reads
   156  	}{
   157  		{12, 15, []string{"0123456789", "ab\x00\x00\x00fghij", "klmn"}},                              // within one read
   158  		{8, 21, []string{"01234567\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00lmn"}}, // across multiple reads
   159  		{10, 20, []string{"0123456789", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "klmn"}},         // a whole read
   160  		{0, 5, []string{"\x00\x00\x00\x00\x0056789", "abcdefghij", "klmn"}},                          // start
   161  		{12, 24, []string{"0123456789", "ab\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00"}},   // end
   162  	}
   163  	p := make([]byte, 10)
   164  	for _, test := range tests {
   165  		r := &excludedReader{strings.NewReader(s), 0, test.start, test.end}
   166  		for _, res := range test.results {
   167  			n, err := r.Read(p)
   168  			if err != nil {
   169  				t.Errorf("read failed: %v", err)
   170  			}
   171  			if n != len(res) {
   172  				t.Errorf("unexpected number of bytes read: want %d, got %d", len(res), n)
   173  			}
   174  			if string(p[:n]) != res {
   175  				t.Errorf("unexpected bytes: want %q, got %q", res, p[:n])
   176  			}
   177  		}
   178  	}
   179  }
   180  
   181  func TestEmptyID(t *testing.T) {
   182  	r := strings.NewReader("aha!")
   183  	matches, hash, err := FindAndHash(r, "", 1000)
   184  	if matches != nil || hash != ([32]byte{}) || err == nil || !strings.Contains(err.Error(), "no id") {
   185  		t.Errorf("FindAndHash: want nil, [32]byte{}, no id specified, got %v, %v, %v", matches, hash, err)
   186  	}
   187  }
   188  

View as plain text