package sonyflake import ( "errors" "fmt" "net" "runtime" "testing" "time" "github.com/sony/sonyflake/mock" "github.com/sony/sonyflake/types" ) var sf *Sonyflake var startTime int64 var machineID uint64 func init() { var st Settings st.StartTime = time.Now() sf = NewSonyflake(st) if sf == nil { panic("sonyflake not created") } startTime = toSonyflakeTime(st.StartTime) ip, _ := lower16BitPrivateIP(defaultInterfaceAddrs) machineID = uint64(ip) } func nextID(t *testing.T) uint64 { id, err := sf.NextID() if err != nil { t.Fatal("id not generated") } return id } func TestNew(t *testing.T) { genError := fmt.Errorf("an error occurred while generating ID") tests := []struct { name string settings Settings err error }{ { name: "failure: time ahead", settings: Settings{ StartTime: time.Now().Add(time.Minute), }, err: ErrStartTimeAhead, }, { name: "failure: machine ID", settings: Settings{ MachineID: func() (uint16, error) { return 0, genError }, }, err: genError, }, { name: "failure: invalid machine ID", settings: Settings{ CheckMachineID: func(uint16) bool { return false }, }, err: ErrInvalidMachineID, }, { name: "success", settings: Settings{}, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { sonyflake, err := New(test.settings) if !errors.Is(err, test.err) { t.Fatalf("unexpected value, want %#v, got %#v", test.err, err) } if sonyflake == nil && err == nil { t.Fatal("unexpected value, sonyflake should not be nil") } }) } } func TestSonyflakeOnce(t *testing.T) { sleepTime := time.Duration(50 * sonyflakeTimeUnit) time.Sleep(sleepTime) id := nextID(t) actualTime := ElapsedTime(id) if actualTime < sleepTime || actualTime > sleepTime+sonyflakeTimeUnit { t.Errorf("unexpected time: %d", actualTime) } actualSequence := SequenceNumber(id) if actualSequence != 0 { t.Errorf("unexpected sequence: %d", actualSequence) } actualMachineID := MachineID(id) if actualMachineID != machineID { t.Errorf("unexpected machine id: %d", actualMachineID) } fmt.Println("sonyflake id:", id) fmt.Println("decompose:", Decompose(id)) } func currentTime() int64 { return toSonyflakeTime(time.Now()) } func TestSonyflakeFor10Sec(t *testing.T) { var numID uint32 var lastID uint64 var maxSequence uint64 initial := currentTime() current := initial for current-initial < 1000 { id := nextID(t) parts := Decompose(id) numID++ if id == lastID { t.Fatal("duplicated id") } if id < lastID { t.Fatal("must increase with time") } lastID = id current = currentTime() actualMSB := parts["msb"] if actualMSB != 0 { t.Errorf("unexpected msb: %d", actualMSB) } actualTime := int64(parts["time"]) overtime := startTime + actualTime - current if overtime > 0 { t.Errorf("unexpected overtime: %d", overtime) } actualSequence := parts["sequence"] if maxSequence < actualSequence { maxSequence = actualSequence } actualMachineID := parts["machine-id"] if actualMachineID != machineID { t.Errorf("unexpected machine id: %d", actualMachineID) } } if maxSequence != 1<