Source file src/internal/runtime/gc/scan/filter_test.go

     1  // Copyright 2025 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 scan_test
     6  
     7  import (
     8  	"internal/runtime/gc/scan"
     9  	"testing"
    10  )
    11  
    12  func TestFilterNil(t *testing.T) {
    13  	t.Run("empty", func(t *testing.T) {
    14  		testFilterNil(t, []uintptr{}, []uintptr{})
    15  	})
    16  	t.Run("one", func(t *testing.T) {
    17  		testFilterNil(t, []uintptr{4}, []uintptr{4})
    18  	})
    19  	t.Run("elimOne", func(t *testing.T) {
    20  		testFilterNil(t, []uintptr{0}, []uintptr{})
    21  	})
    22  	t.Run("oneElimBegin", func(t *testing.T) {
    23  		testFilterNil(t, []uintptr{0, 4}, []uintptr{4})
    24  	})
    25  	t.Run("oneElimEnd", func(t *testing.T) {
    26  		testFilterNil(t, []uintptr{4, 0}, []uintptr{4})
    27  	})
    28  	t.Run("oneElimMultiBegin", func(t *testing.T) {
    29  		testFilterNil(t, []uintptr{0, 0, 0, 4}, []uintptr{4})
    30  	})
    31  	t.Run("oneElimMultiEnd", func(t *testing.T) {
    32  		testFilterNil(t, []uintptr{4, 0, 0, 0}, []uintptr{4})
    33  	})
    34  	t.Run("oneElimMulti", func(t *testing.T) {
    35  		testFilterNil(t, []uintptr{0, 0, 0, 4, 0}, []uintptr{4})
    36  	})
    37  	t.Run("two", func(t *testing.T) {
    38  		testFilterNil(t, []uintptr{5, 12}, []uintptr{5, 12})
    39  	})
    40  	t.Run("twoElimBegin", func(t *testing.T) {
    41  		testFilterNil(t, []uintptr{0, 5, 12}, []uintptr{5, 12})
    42  	})
    43  	t.Run("twoElimMid", func(t *testing.T) {
    44  		testFilterNil(t, []uintptr{5, 0, 12}, []uintptr{5, 12})
    45  	})
    46  	t.Run("twoElimEnd", func(t *testing.T) {
    47  		testFilterNil(t, []uintptr{5, 12, 0}, []uintptr{5, 12})
    48  	})
    49  	t.Run("twoElimMulti", func(t *testing.T) {
    50  		testFilterNil(t, []uintptr{0, 5, 0, 12, 0}, []uintptr{5, 12})
    51  	})
    52  	t.Run("Multi", func(t *testing.T) {
    53  		testFilterNil(t, []uintptr{1, 5, 5, 0, 0, 0, 12, 0, 121, 5, 0}, []uintptr{1, 5, 5, 12, 121, 5})
    54  	})
    55  }
    56  
    57  func testFilterNil(t *testing.T, buf, want []uintptr) {
    58  	var bufp *uintptr
    59  	if len(buf) != 0 {
    60  		bufp = &buf[0]
    61  	}
    62  	n := scan.FilterNil(bufp, int32(len(buf)))
    63  	if n > int32(len(buf)) {
    64  		t.Errorf("bogus new length returned: %d > %d", n, len(buf))
    65  		return
    66  	}
    67  	buf = buf[:n]
    68  	if len(buf) != len(want) {
    69  		t.Errorf("lengths differ: got %d, want %d", len(buf), len(want))
    70  	}
    71  
    72  	wantMap := make(map[uintptr]int)
    73  	gotMap := make(map[uintptr]int)
    74  	for _, p := range want {
    75  		wantMap[p]++
    76  	}
    77  	for _, p := range buf {
    78  		gotMap[p]++
    79  	}
    80  	for p, nWant := range wantMap {
    81  		if nGot, ok := gotMap[p]; !ok {
    82  			t.Errorf("want %d, but missing from output", p)
    83  		} else if nGot != nWant {
    84  			t.Errorf("want %d copies of %d, but got %d", nWant, p, nGot)
    85  		}
    86  	}
    87  	for p := range gotMap {
    88  		if _, ok := wantMap[p]; !ok {
    89  			t.Errorf("got %d, but didn't want it", p)
    90  		}
    91  	}
    92  	t.Logf("got:  %v", buf)
    93  	t.Logf("want: %v", want)
    94  }
    95  

View as plain text