github.com/influx6/npkg@v0.8.8/nxid/id_test.go (about)

     1  package nxid
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  type IDParts struct {
    14  	id        ID
    15  	timestamp int64
    16  	machine   []byte
    17  	pid       uint16
    18  	counter   int32
    19  }
    20  
    21  var IDs = []IDParts{
    22  	IDParts{
    23  		ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9},
    24  		1300816219,
    25  		[]byte{0x60, 0xf4, 0x86},
    26  		0xe428,
    27  		4271561,
    28  	},
    29  	IDParts{
    30  		ID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    31  		0,
    32  		[]byte{0x00, 0x00, 0x00},
    33  		0x0000,
    34  		0,
    35  	},
    36  	IDParts{
    37  		ID{0x00, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x00, 0x01},
    38  		0,
    39  		[]byte{0xaa, 0xbb, 0xcc},
    40  		0xddee,
    41  		1,
    42  	},
    43  }
    44  
    45  func TestIDPartsExtraction(t *testing.T) {
    46  	for i, v := range IDs {
    47  		t.Run(fmt.Sprintf("Test%d", i), func(t *testing.T) {
    48  			if got, want := v.id.Time(), time.Unix(v.timestamp, 0); got != want {
    49  				t.Errorf("Time() = %v, want %v", got, want)
    50  			}
    51  			if got, want := v.id.Machine(), v.machine; !bytes.Equal(got, want) {
    52  				t.Errorf("Machine() = %v, want %v", got, want)
    53  			}
    54  			if got, want := v.id.Pid(), v.pid; got != want {
    55  				t.Errorf("Pid() = %v, want %v", got, want)
    56  			}
    57  			if got, want := v.id.Counter(), v.counter; got != want {
    58  				t.Errorf("Counter() = %v, want %v", got, want)
    59  			}
    60  		})
    61  	}
    62  }
    63  
    64  func TestNew(t *testing.T) {
    65  	// Generate 10 ids
    66  	ids := make([]ID, 10)
    67  	for i := 0; i < 10; i++ {
    68  		ids[i] = New()
    69  	}
    70  	for i := 1; i < 10; i++ {
    71  		prevID := ids[i-1]
    72  		id := ids[i]
    73  		// Test for uniqueness among all other 9 generated ids
    74  		for j, tid := range ids {
    75  			if j != i {
    76  				if id.Compare(tid) == 0 {
    77  					t.Errorf("generated Id is not unique (%d/%d)", i, j)
    78  				}
    79  			}
    80  		}
    81  		// Check that timestamp was incremented and is within 30 seconds of the previous one
    82  		secs := id.Time().Sub(prevID.Time()).Seconds()
    83  		if secs < 0 || secs > 30 {
    84  			t.Error("wrong timestamp in generated Id")
    85  		}
    86  		// Check that machine ids are the same
    87  		if !bytes.Equal(id.Machine(), prevID.Machine()) {
    88  			t.Error("machine Id not equal")
    89  		}
    90  		// Check that pids are the same
    91  		if id.Pid() != prevID.Pid() {
    92  			t.Error("pid not equal")
    93  		}
    94  		// Test for proper increment
    95  		if got, want := int(id.Counter()-prevID.Counter()), 1; got != want {
    96  			t.Errorf("wrong increment in generated Id, delta=%v, want %v", got, want)
    97  		}
    98  	}
    99  }
   100  
   101  func TestIDString(t *testing.T) {
   102  	id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
   103  	if got, want := id.String(), "9m4e2mr0ui3e8a215n4g"; got != want {
   104  		t.Errorf("String() = %v, want %v", got, want)
   105  	}
   106  }
   107  
   108  func TestFromString(t *testing.T) {
   109  	got, err := FromString("9m4e2mr0ui3e8a215n4g")
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
   114  	if got != want {
   115  		t.Errorf("FromString() = %v, want %v", got, want)
   116  	}
   117  }
   118  
   119  func TestFromStringInvalid(t *testing.T) {
   120  	_, err := FromString("invalid")
   121  	if err != ErrInvalidID {
   122  		t.Errorf("FromString(invalid) err=%v, want %v", err, ErrInvalidID)
   123  	}
   124  }
   125  
   126  type jsonType struct {
   127  	ID  *ID
   128  	Str string
   129  }
   130  
   131  func TestIDJSONMarshaling(t *testing.T) {
   132  	id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
   133  	v := jsonType{ID: &id, Str: "test"}
   134  	data, err := json.Marshal(&v)
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	if got, want := string(data), `{"Id":"9m4e2mr0ui3e8a215n4g","Str":"test"}`; got != want {
   139  		t.Errorf("json.Marshal() = %v, want %v", got, want)
   140  	}
   141  }
   142  
   143  func TestIDJSONUnmarshaling(t *testing.T) {
   144  	data := []byte(`{"Id":"9m4e2mr0ui3e8a215n4g","Str":"test"}`)
   145  	v := jsonType{}
   146  	err := json.Unmarshal(data, &v)
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
   151  	if got := *v.ID; got.Compare(want) != 0 {
   152  		t.Errorf("json.Unmarshal() = %v, want %v", got, want)
   153  	}
   154  
   155  }
   156  
   157  func TestIDJSONUnmarshalingError(t *testing.T) {
   158  	v := jsonType{}
   159  	err := json.Unmarshal([]byte(`{"Id":"9M4E2MR0UI3E8A215N4G"}`), &v)
   160  	if err != ErrInvalidID {
   161  		t.Errorf("json.Unmarshal() err=%v, want %v", err, ErrInvalidID)
   162  	}
   163  	err = json.Unmarshal([]byte(`{"Id":"TYjhW2D0huQoQS"}`), &v)
   164  	if err != ErrInvalidID {
   165  		t.Errorf("json.Unmarshal() err=%v, want %v", err, ErrInvalidID)
   166  	}
   167  	err = json.Unmarshal([]byte(`{"Id":"TYjhW2D0huQoQS3kdk"}`), &v)
   168  	if err != ErrInvalidID {
   169  		t.Errorf("json.Unmarshal() err=%v, want %v", err, ErrInvalidID)
   170  	}
   171  }
   172  
   173  func TestIDDriverValue(t *testing.T) {
   174  	id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
   175  	got, err := id.Value()
   176  	if err != nil {
   177  		t.Fatal(err)
   178  	}
   179  	if want := "9m4e2mr0ui3e8a215n4g"; got != want {
   180  		t.Errorf("Value() = %v, want %v", got, want)
   181  	}
   182  }
   183  
   184  func TestIDDriverScan(t *testing.T) {
   185  	got := ID{}
   186  	err := got.Scan("9m4e2mr0ui3e8a215n4g")
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
   191  	if got.Compare(want) != 0 {
   192  		t.Errorf("Scan() = %v, want %v", got, want)
   193  	}
   194  }
   195  
   196  func TestIDDriverScanError(t *testing.T) {
   197  	id := ID{}
   198  	if got, want := id.Scan(0), errors.New("nxid: scanning unsupported type: int"); !reflect.DeepEqual(got, want) {
   199  		t.Errorf("Scan() err=%v, want %v", got, want)
   200  	}
   201  	if got, want := id.Scan("0"), ErrInvalidID; got != want {
   202  		t.Errorf("Scan() err=%v, want %v", got, want)
   203  	}
   204  }
   205  
   206  func TestIDDriverScanByteFromDatabase(t *testing.T) {
   207  	got := ID{}
   208  	bs := []byte("9m4e2mr0ui3e8a215n4g")
   209  	err := got.Scan(bs)
   210  	if err != nil {
   211  		t.Fatal(err)
   212  	}
   213  	want := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}
   214  	if got.Compare(want) != 0 {
   215  		t.Errorf("Scan() = %v, want %v", got, want)
   216  	}
   217  }
   218  
   219  func BenchmarkNew(b *testing.B) {
   220  	b.RunParallel(func(pb *testing.PB) {
   221  		for pb.Next() {
   222  			_ = New()
   223  		}
   224  	})
   225  }
   226  
   227  func BenchmarkNewString(b *testing.B) {
   228  	b.RunParallel(func(pb *testing.PB) {
   229  		for pb.Next() {
   230  			_ = New().String()
   231  		}
   232  	})
   233  }
   234  
   235  func BenchmarkFromString(b *testing.B) {
   236  	b.RunParallel(func(pb *testing.PB) {
   237  		for pb.Next() {
   238  			_, _ = FromString("9m4e2mr0ui3e8a215n4g")
   239  		}
   240  	})
   241  }
   242  
   243  // func BenchmarkUUIDv1(b *testing.B) {
   244  // 	b.RunParallel(func(pb *testing.PB) {
   245  // 		for pb.Next() {
   246  // 			_ = uuid.NewV1().String()
   247  // 		}
   248  // 	})
   249  // }
   250  
   251  // func BenchmarkUUIDv4(b *testing.B) {
   252  // 	b.RunParallel(func(pb *testing.PB) {
   253  // 		for pb.Next() {
   254  // 			_ = uuid.NewV4().String()
   255  // 		}
   256  // 	})
   257  // }
   258  
   259  func TestID_IsNil(t *testing.T) {
   260  	tests := []struct {
   261  		name string
   262  		id   ID
   263  		want bool
   264  	}{
   265  		{
   266  			name: "Id not nil",
   267  			id:   New(),
   268  			want: false,
   269  		},
   270  		{
   271  			name: "Nil Id",
   272  			id:   ID{},
   273  			want: true,
   274  		},
   275  	}
   276  	for _, tt := range tests {
   277  		tt := tt
   278  		t.Run(tt.name, func(t *testing.T) {
   279  			if got, want := tt.id.IsNil(), tt.want; got != want {
   280  				t.Errorf("IsNil() = %v, want %v", got, want)
   281  			}
   282  		})
   283  	}
   284  }
   285  
   286  func TestNilID(t *testing.T) {
   287  	got := ID{}
   288  	if want := NilID(); !reflect.DeepEqual(got, want) {
   289  		t.Error("NilID() not equal Id{}")
   290  	}
   291  }
   292  
   293  func TestNilID_IsNil(t *testing.T) {
   294  	if !NilID().IsNil() {
   295  		t.Error("NilID().IsNil() is not true")
   296  	}
   297  }
   298  
   299  func TestFromBytes_Invariant(t *testing.T) {
   300  	want := New()
   301  	got, err := FromBytes(want.Bytes())
   302  	if err != nil {
   303  		t.Fatal(err)
   304  	}
   305  	if got.Compare(want) != 0 {
   306  		t.Error("FromBytes(id.Bytes()) != id")
   307  	}
   308  }
   309  
   310  func TestFromBytes_InvalidBytes(t *testing.T) {
   311  	cases := []struct {
   312  		length     int
   313  		shouldFail bool
   314  	}{
   315  		{11, true},
   316  		{12, false},
   317  		{13, true},
   318  	}
   319  	for _, c := range cases {
   320  		b := make([]byte, c.length, c.length)
   321  		_, err := FromBytes(b)
   322  		if got, want := err != nil, c.shouldFail; got != want {
   323  			t.Errorf("FromBytes() error got %v, want %v", got, want)
   324  		}
   325  	}
   326  }
   327  
   328  func TestID_Compare(t *testing.T) {
   329  	pairs := []struct {
   330  		left     ID
   331  		right    ID
   332  		expected int
   333  	}{
   334  		{IDs[1].id, IDs[0].id, -1},
   335  		{ID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, IDs[2].id, -1},
   336  		{IDs[0].id, IDs[0].id, 0},
   337  	}
   338  	for _, p := range pairs {
   339  		if p.expected != p.left.Compare(p.right) {
   340  			t.Errorf("%s Compare to %s should return %d", p.left, p.right, p.expected)
   341  		}
   342  		if -1*p.expected != p.right.Compare(p.left) {
   343  			t.Errorf("%s Compare to %s should return %d", p.right, p.left, -1*p.expected)
   344  		}
   345  	}
   346  }
   347  
   348  var IDList = []ID{IDs[0].id, IDs[1].id, IDs[2].id}
   349  
   350  func TestSorter_Len(t *testing.T) {
   351  	if got, want := sorter([]ID{}).Len(), 0; got != want {
   352  		t.Errorf("Len() %v, want %v", got, want)
   353  	}
   354  	if got, want := sorter(IDList).Len(), 3; got != want {
   355  		t.Errorf("Len() %v, want %v", got, want)
   356  	}
   357  }
   358  
   359  func TestSorter_Less(t *testing.T) {
   360  	sorter := sorter(IDList)
   361  	if !sorter.Less(1, 0) {
   362  		t.Errorf("Less(1, 0) not true")
   363  	}
   364  	if sorter.Less(2, 1) {
   365  		t.Errorf("Less(2, 1) true")
   366  	}
   367  	if sorter.Less(0, 0) {
   368  		t.Errorf("Less(0, 0) true")
   369  	}
   370  }
   371  
   372  func TestSorter_Swap(t *testing.T) {
   373  	ids := make([]ID, 0)
   374  	ids = append(ids, IDList...)
   375  	sorter := sorter(ids)
   376  	sorter.Swap(0, 1)
   377  	if got, want := ids[0], IDList[1]; !reflect.DeepEqual(got, want) {
   378  		t.Error("ids[0] != IDList[1]")
   379  	}
   380  	if got, want := ids[1], IDList[0]; !reflect.DeepEqual(got, want) {
   381  		t.Error("ids[1] != IDList[0]")
   382  	}
   383  	sorter.Swap(2, 2)
   384  	if got, want := ids[2], IDList[2]; !reflect.DeepEqual(got, want) {
   385  		t.Error("ids[2], IDList[2]")
   386  	}
   387  }
   388  
   389  func TestSort(t *testing.T) {
   390  	ids := make([]ID, 0)
   391  	ids = append(ids, IDList...)
   392  	Sort(ids)
   393  	if got, want := ids, []ID{IDList[1], IDList[2], IDList[0]}; !reflect.DeepEqual(got, want) {
   394  		t.Fail()
   395  	}
   396  }