github.com/anacrolix/torrent@v1.61.0/internal/indexed/map_test.go (about)

     1  package indexed
     2  
     3  import (
     4  	"cmp"
     5  	"slices"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/anacrolix/missinggo/v2/panicif"
    10  	"github.com/anacrolix/torrent/internal/extracmp"
    11  	"github.com/go-quicktest/qt"
    12  	"golang.org/x/exp/constraints"
    13  )
    14  
    15  type overdueRecord struct {
    16  	active  bool
    17  	overdue bool
    18  	when    time.Time
    19  }
    20  
    21  type overdueRecordPrimaryKey int
    22  
    23  func (me overdueRecordPrimaryKey) Compare(other overdueRecordPrimaryKey) int {
    24  	return cmp.Compare(me, other)
    25  }
    26  
    27  func overdueRecordIndexCompare(l, r overdueRecord) int {
    28  	return cmp.Or(
    29  		extracmp.CompareBool(l.active, r.active),
    30  		-extracmp.CompareBool(l.overdue, r.overdue),
    31  		l.when.Compare(r.when))
    32  }
    33  
    34  func TestOverdue(t *testing.T) {
    35  	var a Map[int, overdueRecord]
    36  	a.Init(func(a, b int) int {
    37  		return cmp.Compare(a, b)
    38  	})
    39  	idx := NewFullMappedIndex(
    40  		&a,
    41  		func(a, b Pair[overdueRecord, int]) int {
    42  			return cmp.Or(overdueRecordIndexCompare(a.Left, b.Left), cmp.Compare(a.Right, b.Right))
    43  		},
    44  		Pair[int, overdueRecord].Flip,
    45  		func() (ret Pair[overdueRecord, int]) {
    46  			ret.Left.overdue = true
    47  			return
    48  		}(),
    49  	)
    50  	qt.Assert(t, qt.CmpEquals(nil, slices.Collect(a.Iter)))
    51  	rows := []overdueRecord{
    52  		{overdue: true},
    53  		{overdue: true, when: time.Now().Add(-time.Minute)},
    54  		{overdue: true, when: time.Now().Add(time.Minute)},
    55  		{overdue: false, when: time.Now().Add(-time.Minute)},
    56  		{overdue: false, when: time.Now().Add(time.Minute)},
    57  		{overdue: true},
    58  		{overdue: false},
    59  		{overdue: false, active: true},
    60  	}
    61  	for i, row := range rows {
    62  		panicif.False(a.Create(i, row))
    63  	}
    64  	itered := slices.Collect(MapPairIterLeft(a.Iter))
    65  	qt.Assert(t, qt.HasLen(itered, len(rows)))
    66  	iteredPks := slices.Collect(MapPairIterRight(idx.Iter))
    67  	qt.Assert(t, qt.CmpEquals([]int{0, 5, 1, 2, 6, 3, 4, 7}, iteredPks))
    68  	var overdue []int
    69  	gte := idx.MinRecord()
    70  	gte.Left.overdue = false
    71  	lt := gte
    72  	lt.Left.when = time.Now().Add(1)
    73  	for rowid := range MapPairIterRight(IterRange(idx, gte, lt)) {
    74  		overdue = append(overdue, rowid)
    75  	}
    76  	qt.Assert(t, qt.CmpEquals(overdue, []int{6, 3}))
    77  	for _, pk := range overdue {
    78  		a.Update(pk, func(r overdueRecord) overdueRecord {
    79  			r.overdue = true
    80  			return r
    81  		})
    82  	}
    83  	qt.Assert(t, qt.CmpEquals([]int{0, 5, 6, 1, 3, 2, 4, 7}, slices.Collect(MapPairIterRight(idx.Iter))))
    84  }
    85  
    86  type orderedPrimaryKey[T constraints.Ordered] struct {
    87  	inner T
    88  }
    89  
    90  func (me orderedPrimaryKey[T]) Compare(other orderedPrimaryKey[T]) int {
    91  	return cmp.Compare(me.inner, other.inner)
    92  }
    93  
    94  func TestEnsureAndUpdate(t *testing.T) {
    95  	var a Table[int]
    96  	a.Init(cmp.Compare[int])
    97  	a.Create(1)
    98  	a.Update(1, func(r int) int {
    99  		// Check the record was created with the necessary key values for discovery.
   100  		panicif.NotEq(r, 1)
   101  		return r
   102  	})
   103  }