mirror of
https://github.com/golang/go
synced 2024-11-07 12:26:16 -07:00
64dc25b2db
Change-Id: I249deb482df74068b0538e9d773b9a87bc5a6df3 Reviewed-on: https://go-review.googlesource.com/c/go/+/242681 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Michael Knyszek <mknyszek@google.com> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
276 lines
5.7 KiB
Go
276 lines
5.7 KiB
Go
// Copyright 2020 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 runtime_test
|
|
|
|
import (
|
|
. "runtime"
|
|
"testing"
|
|
)
|
|
|
|
func validateAddrRanges(t *testing.T, a *AddrRanges, want ...AddrRange) {
|
|
ranges := a.Ranges()
|
|
if len(ranges) != len(want) {
|
|
t.Errorf("want %v, got %v", want, ranges)
|
|
t.Fatal("different lengths")
|
|
}
|
|
gotTotalBytes := uintptr(0)
|
|
wantTotalBytes := uintptr(0)
|
|
for i := range ranges {
|
|
gotTotalBytes += ranges[i].Size()
|
|
wantTotalBytes += want[i].Size()
|
|
if ranges[i].Base() >= ranges[i].Limit() {
|
|
t.Error("empty range found")
|
|
}
|
|
// Ensure this is equivalent to what we want.
|
|
if !ranges[i].Equals(want[i]) {
|
|
t.Errorf("range %d: got [0x%x, 0x%x), want [0x%x, 0x%x)", i,
|
|
ranges[i].Base(), ranges[i].Limit(),
|
|
want[i].Base(), want[i].Limit(),
|
|
)
|
|
}
|
|
if i != 0 {
|
|
// Ensure the ranges are sorted.
|
|
if ranges[i-1].Base() >= ranges[i].Base() {
|
|
t.Errorf("ranges %d and %d are out of sorted order", i-1, i)
|
|
}
|
|
// Check for a failure to coalesce.
|
|
if ranges[i-1].Limit() == ranges[i].Base() {
|
|
t.Errorf("ranges %d and %d should have coalesced", i-1, i)
|
|
}
|
|
// Check if any ranges overlap. Because the ranges are sorted
|
|
// by base, it's sufficient to just check neighbors.
|
|
if ranges[i-1].Limit() > ranges[i].Base() {
|
|
t.Errorf("ranges %d and %d overlap", i-1, i)
|
|
}
|
|
}
|
|
}
|
|
if wantTotalBytes != gotTotalBytes {
|
|
t.Errorf("expected %d total bytes, got %d", wantTotalBytes, gotTotalBytes)
|
|
}
|
|
if b := a.TotalBytes(); b != gotTotalBytes {
|
|
t.Errorf("inconsistent total bytes: want %d, got %d", gotTotalBytes, b)
|
|
}
|
|
if t.Failed() {
|
|
t.Errorf("addrRanges: %v", ranges)
|
|
t.Fatal("detected bad addrRanges")
|
|
}
|
|
}
|
|
|
|
func TestAddrRangesAdd(t *testing.T) {
|
|
a := NewAddrRanges()
|
|
|
|
// First range.
|
|
a.Add(MakeAddrRange(512, 1024))
|
|
validateAddrRanges(t, &a,
|
|
MakeAddrRange(512, 1024),
|
|
)
|
|
|
|
// Coalesce up.
|
|
a.Add(MakeAddrRange(1024, 2048))
|
|
validateAddrRanges(t, &a,
|
|
MakeAddrRange(512, 2048),
|
|
)
|
|
|
|
// Add new independent range.
|
|
a.Add(MakeAddrRange(4096, 8192))
|
|
validateAddrRanges(t, &a,
|
|
MakeAddrRange(512, 2048),
|
|
MakeAddrRange(4096, 8192),
|
|
)
|
|
|
|
// Coalesce down.
|
|
a.Add(MakeAddrRange(3776, 4096))
|
|
validateAddrRanges(t, &a,
|
|
MakeAddrRange(512, 2048),
|
|
MakeAddrRange(3776, 8192),
|
|
)
|
|
|
|
// Coalesce up and down.
|
|
a.Add(MakeAddrRange(2048, 3776))
|
|
validateAddrRanges(t, &a,
|
|
MakeAddrRange(512, 8192),
|
|
)
|
|
|
|
// Push a bunch of independent ranges to the end to try and force growth.
|
|
expectedRanges := []AddrRange{MakeAddrRange(512, 8192)}
|
|
for i := uintptr(0); i < 64; i++ {
|
|
dRange := MakeAddrRange(8192+(i+1)*2048, 8192+(i+1)*2048+10)
|
|
a.Add(dRange)
|
|
expectedRanges = append(expectedRanges, dRange)
|
|
validateAddrRanges(t, &a, expectedRanges...)
|
|
}
|
|
|
|
// Push a bunch of independent ranges to the beginning to try and force growth.
|
|
var bottomRanges []AddrRange
|
|
for i := uintptr(0); i < 63; i++ {
|
|
dRange := MakeAddrRange(8+i*8, 8+i*8+4)
|
|
a.Add(dRange)
|
|
bottomRanges = append(bottomRanges, dRange)
|
|
validateAddrRanges(t, &a, append(bottomRanges, expectedRanges...)...)
|
|
}
|
|
}
|
|
|
|
func TestAddrRangesFindSucc(t *testing.T) {
|
|
var large []AddrRange
|
|
for i := 0; i < 100; i++ {
|
|
large = append(large, MakeAddrRange(5+uintptr(i)*5, 5+uintptr(i)*5+3))
|
|
}
|
|
|
|
type testt struct {
|
|
name string
|
|
base uintptr
|
|
expect int
|
|
ranges []AddrRange
|
|
}
|
|
tests := []testt{
|
|
{
|
|
name: "Empty",
|
|
base: 12,
|
|
expect: 0,
|
|
ranges: []AddrRange{},
|
|
},
|
|
{
|
|
name: "OneBefore",
|
|
base: 12,
|
|
expect: 0,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(14, 16),
|
|
},
|
|
},
|
|
{
|
|
name: "OneWithin",
|
|
base: 14,
|
|
expect: 1,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(14, 16),
|
|
},
|
|
},
|
|
{
|
|
name: "OneAfterLimit",
|
|
base: 16,
|
|
expect: 1,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(14, 16),
|
|
},
|
|
},
|
|
{
|
|
name: "OneAfter",
|
|
base: 17,
|
|
expect: 1,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(14, 16),
|
|
},
|
|
},
|
|
{
|
|
name: "ThreeBefore",
|
|
base: 3,
|
|
expect: 0,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(6, 10),
|
|
MakeAddrRange(12, 16),
|
|
MakeAddrRange(19, 22),
|
|
},
|
|
},
|
|
{
|
|
name: "ThreeAfter",
|
|
base: 24,
|
|
expect: 3,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(6, 10),
|
|
MakeAddrRange(12, 16),
|
|
MakeAddrRange(19, 22),
|
|
},
|
|
},
|
|
{
|
|
name: "ThreeBetween",
|
|
base: 11,
|
|
expect: 1,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(6, 10),
|
|
MakeAddrRange(12, 16),
|
|
MakeAddrRange(19, 22),
|
|
},
|
|
},
|
|
{
|
|
name: "ThreeWithin",
|
|
base: 9,
|
|
expect: 1,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(6, 10),
|
|
MakeAddrRange(12, 16),
|
|
MakeAddrRange(19, 22),
|
|
},
|
|
},
|
|
{
|
|
name: "Zero",
|
|
base: 0,
|
|
expect: 1,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(0, 10),
|
|
},
|
|
},
|
|
{
|
|
name: "Max",
|
|
base: ^uintptr(0),
|
|
expect: 1,
|
|
ranges: []AddrRange{
|
|
MakeAddrRange(^uintptr(0)-5, ^uintptr(0)),
|
|
},
|
|
},
|
|
{
|
|
name: "LargeBefore",
|
|
base: 2,
|
|
expect: 0,
|
|
ranges: large,
|
|
},
|
|
{
|
|
name: "LargeAfter",
|
|
base: 5 + uintptr(len(large))*5 + 30,
|
|
expect: len(large),
|
|
ranges: large,
|
|
},
|
|
{
|
|
name: "LargeBetweenLow",
|
|
base: 14,
|
|
expect: 2,
|
|
ranges: large,
|
|
},
|
|
{
|
|
name: "LargeBetweenHigh",
|
|
base: 249,
|
|
expect: 49,
|
|
ranges: large,
|
|
},
|
|
{
|
|
name: "LargeWithinLow",
|
|
base: 25,
|
|
expect: 5,
|
|
ranges: large,
|
|
},
|
|
{
|
|
name: "LargeWithinHigh",
|
|
base: 396,
|
|
expect: 79,
|
|
ranges: large,
|
|
},
|
|
{
|
|
name: "LargeWithinMiddle",
|
|
base: 250,
|
|
expect: 50,
|
|
ranges: large,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
a := MakeAddrRanges(test.ranges...)
|
|
i := a.FindSucc(test.base)
|
|
if i != test.expect {
|
|
t.Fatalf("expected %d, got %d", test.expect, i)
|
|
}
|
|
})
|
|
}
|
|
}
|