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

View as plain text