github.com/bigcommerce/nomad@v0.9.3-bc/nomad/timetable_test.go (about) 1 package nomad 2 3 import ( 4 "bytes" 5 "sync" 6 "testing" 7 "time" 8 9 "github.com/google/go-cmp/cmp" 10 "github.com/google/go-cmp/cmp/cmpopts" 11 "github.com/hashicorp/nomad/nomad/structs" 12 "github.com/ugorji/go/codec" 13 ) 14 15 func TestTimeTable(t *testing.T) { 16 t.Parallel() 17 tt := NewTimeTable(time.Second, time.Minute) 18 19 index := tt.NearestIndex(time.Now()) 20 if index != 0 { 21 t.Fatalf("bad: %v", index) 22 } 23 24 when := tt.NearestTime(1000) 25 if !when.IsZero() { 26 t.Fatalf("bad: %v", when) 27 } 28 29 // Witness some data 30 start := time.Now() 31 plusOne := start.Add(time.Minute) 32 plusTwo := start.Add(2 * time.Minute) 33 plusFive := start.Add(5 * time.Minute) 34 plusThirty := start.Add(30 * time.Minute) 35 plusHour := start.Add(60 * time.Minute) 36 plusHourHalf := start.Add(90 * time.Minute) 37 38 tt.Witness(2, start) 39 tt.Witness(2, start) 40 41 tt.Witness(10, plusOne) 42 tt.Witness(10, plusOne) 43 44 tt.Witness(20, plusTwo) 45 tt.Witness(20, plusTwo) 46 47 tt.Witness(30, plusFive) 48 tt.Witness(30, plusFive) 49 50 tt.Witness(40, plusThirty) 51 tt.Witness(40, plusThirty) 52 53 tt.Witness(50, plusHour) 54 tt.Witness(50, plusHour) 55 56 type tcase struct { 57 when time.Time 58 expectIndex uint64 59 60 index uint64 61 expectWhen time.Time 62 } 63 cases := []tcase{ 64 // Exact match 65 {start, 2, 2, start}, 66 {plusOne, 10, 10, plusOne}, 67 {plusHour, 50, 50, plusHour}, 68 69 // Before the newest entry 70 {plusHourHalf, 50, 51, plusHour}, 71 72 // After the oldest entry 73 {time.Time{}, 0, 1, time.Time{}}, 74 75 // Mid range 76 {start.Add(3 * time.Minute), 20, 25, plusTwo}, 77 } 78 79 for _, tc := range cases { 80 index := tt.NearestIndex(tc.when) 81 if index != tc.expectIndex { 82 t.Fatalf("bad: %v %v", index, tc.expectIndex) 83 } 84 85 when := tt.NearestTime(tc.index) 86 if when != tc.expectWhen { 87 t.Fatalf("bad: for %d %v %v", tc.index, when, tc.expectWhen) 88 } 89 } 90 } 91 92 func TestTimeTable_SerializeDeserialize(t *testing.T) { 93 t.Parallel() 94 tt := NewTimeTable(time.Second, time.Minute) 95 96 // Witness some data 97 start := time.Now() 98 plusOne := start.Add(time.Minute) 99 plusTwo := start.Add(2 * time.Minute) 100 plusFive := start.Add(5 * time.Minute) 101 plusThirty := start.Add(30 * time.Minute) 102 plusHour := start.Add(60 * time.Minute) 103 104 tt.Witness(2, start) 105 tt.Witness(10, plusOne) 106 tt.Witness(20, plusTwo) 107 tt.Witness(30, plusFive) 108 tt.Witness(40, plusThirty) 109 tt.Witness(50, plusHour) 110 111 var buf bytes.Buffer 112 enc := codec.NewEncoder(&buf, structs.MsgpackHandle) 113 114 err := tt.Serialize(enc) 115 if err != nil { 116 t.Fatalf("err: %v", err) 117 } 118 119 dec := codec.NewDecoder(&buf, structs.MsgpackHandle) 120 121 tt2 := NewTimeTable(time.Second, time.Minute) 122 err = tt2.Deserialize(dec) 123 if err != nil { 124 t.Fatalf("err: %v", err) 125 } 126 127 o := cmp.AllowUnexported(TimeTable{}) 128 o2 := cmpopts.IgnoreTypes(sync.RWMutex{}) 129 if !cmp.Equal(tt.table, tt2.table, o, o2) { 130 t.Fatalf("bad: %s", cmp.Diff(tt, tt2, o, o2)) 131 } 132 } 133 134 func TestTimeTable_Overflow(t *testing.T) { 135 t.Parallel() 136 tt := NewTimeTable(time.Second, 3*time.Second) 137 138 // Witness some data 139 start := time.Now() 140 plusOne := start.Add(time.Second) 141 plusTwo := start.Add(2 * time.Second) 142 plusThree := start.Add(3 * time.Second) 143 144 tt.Witness(10, start) 145 tt.Witness(20, plusOne) 146 tt.Witness(30, plusTwo) 147 tt.Witness(40, plusThree) 148 149 if len(tt.table) != 3 { 150 t.Fatalf("bad") 151 } 152 153 index := tt.NearestIndex(start) 154 if index != 0 { 155 t.Fatalf("bad: %v %v", index, 0) 156 } 157 158 when := tt.NearestTime(15) 159 if !when.IsZero() { 160 t.Fatalf("bad: %v", when) 161 } 162 }