1
2
3
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
33
34
35
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
155 results []string
156 }{
157 {12, 15, []string{"0123456789", "ab\x00\x00\x00fghij", "klmn"}},
158 {8, 21, []string{"01234567\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00lmn"}},
159 {10, 20, []string{"0123456789", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "klmn"}},
160 {0, 5, []string{"\x00\x00\x00\x00\x0056789", "abcdefghij", "klmn"}},
161 {12, 24, []string{"0123456789", "ab\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00"}},
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