blob: c598dcdf8d5dd546a471e2f238af0b0940e22b45 [file] [log] [blame] [edit]
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package buildinfo
import (
"bytes"
"fmt"
"io"
"testing"
)
type byteExe struct {
b []byte
}
func (x *byteExe) DataReader(addr uint64) (io.ReaderAt, error) {
if addr >= uint64(len(x.b)) {
return nil, fmt.Errorf("ReadData(%d) out of bounds of %d-byte slice", addr, len(x.b))
}
return bytes.NewReader(x.b[addr:]), nil
}
func (x *byteExe) DataStart() (uint64, uint64) {
return 0, uint64(len(x.b))
}
func TestSearchMagic(t *testing.T) {
tests := []struct {
name string
data []byte
want uint64
wantErr error
}{
{
name: "beginning",
data: func() []byte {
b := make([]byte, buildInfoHeaderSize)
copy(b, buildInfoMagic)
return b
}(),
want: 0,
},
{
name: "offset",
data: func() []byte {
b := make([]byte, 512)
copy(b[4*buildInfoAlign:], buildInfoMagic)
return b
}(),
want: 4 * buildInfoAlign,
},
{
name: "second_chunk",
data: func() []byte {
b := make([]byte, 4*searchChunkSize)
copy(b[searchChunkSize+4*buildInfoAlign:], buildInfoMagic)
return b
}(),
want: searchChunkSize + 4*buildInfoAlign,
},
{
name: "second_chunk_short",
data: func() []byte {
// Magic is 64-bytes into the second chunk,
// which is short; only exactly long enough to
// hold the header.
b := make([]byte, searchChunkSize+4*buildInfoAlign+buildInfoHeaderSize)
copy(b[searchChunkSize+4*buildInfoAlign:], buildInfoMagic)
return b
}(),
want: searchChunkSize + 4*buildInfoAlign,
},
{
name: "missing",
data: func() []byte {
b := make([]byte, buildInfoHeaderSize)
return b
}(),
wantErr: errNotGoExe,
},
{
name: "too_short",
data: func() []byte {
// There needs to be space for the entire
// header, not just the magic.
b := make([]byte, len(buildInfoMagic))
copy(b, buildInfoMagic)
return b
}(),
wantErr: errNotGoExe,
},
{
name: "misaligned",
data: func() []byte {
b := make([]byte, 512)
copy(b[7:], buildInfoMagic)
return b
}(),
wantErr: errNotGoExe,
},
{
name: "misaligned_across_chunk",
data: func() []byte {
// Magic crosses chunk boundary. By definition,
// it has to be misaligned.
b := make([]byte, 2*searchChunkSize)
copy(b[searchChunkSize-8:], buildInfoMagic)
return b
}(),
wantErr: errNotGoExe,
},
{
name: "header_across_chunk",
data: func() []byte {
// The magic is aligned within the first chunk,
// but the rest of the 32-byte header crosses
// the chunk boundary.
b := make([]byte, 2*searchChunkSize)
copy(b[searchChunkSize-buildInfoAlign:], buildInfoMagic)
return b
}(),
want: searchChunkSize - buildInfoAlign,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
x := &byteExe{tc.data}
dataAddr, dataSize := x.DataStart()
addr, err := searchMagic(x, dataAddr, dataSize)
if tc.wantErr == nil {
if err != nil {
t.Errorf("searchMagic got err %v want nil", err)
}
if addr != tc.want {
t.Errorf("searchMagic got addr %d want %d", addr, tc.want)
}
} else {
if err != tc.wantErr {
t.Errorf("searchMagic got err %v want %v", err, tc.wantErr)
}
}
})
}
}