| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- package job
- import (
- "sync"
- "testing"
- "github.com/mhsanaei/3x-ui/v3/internal/database/model"
- )
- func TestAtomicBool_DefaultIsFalse(t *testing.T) {
- var a atomicBool
- if a.takeAndReset() {
- t.Fatal("default atomicBool should report false")
- }
- }
- func TestAtomicBool_SetThenTakeReturnsTrueOnce(t *testing.T) {
- var a atomicBool
- a.set()
- if !a.takeAndReset() {
- t.Fatal("takeAndReset after set should return true")
- }
- if a.takeAndReset() {
- t.Fatal("second takeAndReset should return false (state was reset)")
- }
- }
- func TestAtomicBool_SetIsIdempotent(t *testing.T) {
- var a atomicBool
- a.set()
- a.set()
- a.set()
- if !a.takeAndReset() {
- t.Fatal("repeated set should still leave the flag true")
- }
- if a.takeAndReset() {
- t.Fatal("flag should be cleared after the first take")
- }
- }
- func TestAtomicBool_ConcurrentSettersExactlyOneTakeWins(t *testing.T) {
- var a atomicBool
- const setters = 100
- const readers = 20
- var wg sync.WaitGroup
- for range setters {
- wg.Go(func() {
- a.set()
- })
- }
- wg.Wait()
- trueCount := 0
- var rwg sync.WaitGroup
- var mu sync.Mutex
- for range readers {
- rwg.Go(func() {
- if a.takeAndReset() {
- mu.Lock()
- trueCount++
- mu.Unlock()
- }
- })
- }
- rwg.Wait()
- if trueCount != 1 {
- t.Fatalf("expected exactly one reader to observe true, got %d", trueCount)
- }
- }
- // Regression (#6283): a node onboarded in selected mode with an empty tag
- // list empties its snapshot via FilterNodeSnapshot before the merge sees it,
- // so that sync adopts nothing and must not stamp InboundsAdoptedAt.
- func TestSyncCanAdoptInbounds(t *testing.T) {
- cases := []struct {
- name string
- node *model.Node
- aliases []string
- expected bool
- }{
- {"all mode always adopts", &model.Node{InboundSyncMode: "all"}, nil, true},
- {
- "selected with tags adopts",
- &model.Node{InboundSyncMode: "selected", InboundTags: []string{"in-443-tcp"}},
- nil,
- true,
- },
- {
- "selected empty with adopted alias adopts",
- &model.Node{InboundSyncMode: "selected"},
- []string{"in-443-tcp"},
- true,
- },
- {
- // The reported bug: registering in selected mode and choosing
- // tags afterwards stamped adoption while adopting nothing.
- "selected empty with no aliases adopts nothing",
- &model.Node{InboundSyncMode: "selected"},
- nil,
- false,
- },
- }
- for _, c := range cases {
- t.Run(c.name, func(t *testing.T) {
- if got := syncCanAdoptInbounds(c.node, c.aliases); got != c.expected {
- t.Fatalf("syncCanAdoptInbounds(%+v, %v) = %v, want %v", c.node, c.aliases, got, c.expected)
- }
- })
- }
- }
|