package frame import ( "encoding/binary" "io" "os" "testing" "unsafe" ) func ptrSizeByRuntimeArch() int { return int(unsafe.Sizeof(uintptr(0))) } func TestFDEForPC(t *testing.T) { frames := newFrameIndex() frames = append(frames, &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 50, size: 50}, &FrameDescriptionEntry{begin: 100, size: 100}, &FrameDescriptionEntry{begin: 300, size: 10}) for _, test := range []struct { pc uint64 fde *FrameDescriptionEntry }{ {0, nil}, {9, nil}, {10, frames[0]}, {35, frames[0]}, {49, frames[0]}, {50, frames[1]}, {75, frames[1]}, {100, frames[2]}, {199, frames[2]}, {200, nil}, {299, nil}, {300, frames[3]}, {309, frames[3]}, {310, nil}, {400, nil}} { out, err := frames.FDEForPC(test.pc) if test.fde != nil { if err != nil { t.Fatal(err) } if out != test.fde { t.Errorf("[pc = %#x] got incorrect fde\noutput:\t%#v\nexpected:\t%#v", test.pc, out, test.fde) } } else { if err == nil { t.Errorf("[pc = %#x] expected error got fde %#v", test.pc, out) } } } } func TestAppend(t *testing.T) { equal := func(x, y FrameDescriptionEntries) bool { if len(x) != len(y) { return false } for i := range x { if x[i].Begin() != y[i].Begin() || x[i].End() != y[i].End() { return false } } return true } var appendTests = []struct { name string f1 FrameDescriptionEntries f2 FrameDescriptionEntries want FrameDescriptionEntries }{ { name: "nil", f1: nil, f2: nil, want: nil, }, { name: "one", f1: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, }, f2: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, }, want: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, }, }, { name: "1 item", f1: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 50, size: 50}, }, f2: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 50, size: 50}, }, want: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 50, size: 50}, }, }, { name: "many", f1: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 100, size: 100}, &FrameDescriptionEntry{begin: 50, size: 50}, &FrameDescriptionEntry{begin: 50, size: 50}, &FrameDescriptionEntry{begin: 300, size: 10}, &FrameDescriptionEntry{begin: 300, size: 10}, }, f2: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 100, size: 100}, &FrameDescriptionEntry{begin: 100, size: 100}, }, want: FrameDescriptionEntries{ &FrameDescriptionEntry{begin: 10, size: 40}, &FrameDescriptionEntry{begin: 50, size: 50}, &FrameDescriptionEntry{begin: 100, size: 100}, &FrameDescriptionEntry{begin: 300, size: 10}, }, }, } for _, test := range appendTests { if got := test.f1.Append(test.f2); !equal(got, test.want) { t.Errorf("%v.Append(%v) = %v, want %v", test.f1, test.f2, got, test.want) } } } func BenchmarkFDEForPC(b *testing.B) { f, err := os.Open("testdata/frame") if err != nil { b.Fatal(err) } defer f.Close() data, err := io.ReadAll(f) if err != nil { b.Fatal(err) } fdes, _ := Parse(data, binary.BigEndian, 0, ptrSizeByRuntimeArch(), 0) for i := 0; i < b.N; i++ { // bench worst case, exhaustive search _, _ = fdes.FDEForPC(0x455555555) } }