github.com/grailbio/base@v0.0.11/cloud/spotfeed/querier_test.go (about) 1 package spotfeed 2 3 import ( 4 "testing" 5 "time" 6 ) 7 8 func TestQuerier(t *testing.T) { 9 now := time.Now().Truncate(time.Second) 10 iid, typ := "some-instance-id", "some-instance-type" 11 entries := []*Entry{ 12 {ChargeUSD: 60, Timestamp: now.Add(-60 * time.Minute), InstanceID: iid, Instance: typ}, 13 {ChargeUSD: 110 /*ignored*/, Timestamp: now, InstanceID: iid, Instance: typ}, 14 {ChargeUSD: 120, Timestamp: now, InstanceID: iid, Instance: typ}, 15 {ChargeUSD: 80 /*ignored*/, Timestamp: now.Add(59 * time.Minute), InstanceID: iid, Instance: typ}, 16 {ChargeUSD: 90, Timestamp: now.Add(59 * time.Minute), InstanceID: iid, Instance: typ}, 17 {ChargeUSD: 120, Timestamp: now.Add(121 * time.Minute), InstanceID: iid, Instance: typ}, 18 {ChargeUSD: 88 /*ignored*/, Timestamp: now.Add(3 * time.Hour), InstanceID: iid, Instance: typ}, 19 {ChargeUSD: 89 /*ignored*/, Timestamp: now.Add(3 * time.Hour), InstanceID: iid, Instance: typ}, 20 {ChargeUSD: 90 /*duplicate*/, Timestamp: now.Add(3 * time.Hour), InstanceID: iid, Instance: typ}, 21 {ChargeUSD: 90, Timestamp: now.Add(3 * time.Hour), InstanceID: iid, Instance: typ}, 22 } 23 terminated := now.Add(3*time.Hour + 30*time.Minute) 24 q := newQuerier(entries) 25 _, err := q.Query("some-other-instance-id", Period{}, time.Time{}) 26 if got, want := err, ErrMissingData; got != want { 27 t.Errorf("got %v, want %v", got, want) 28 } 29 for i, tt := range []struct { 30 iet time.Time 31 p Period 32 c Cost 33 wantE error 34 }{ 35 { // Period starting and ending before data. 36 time.Time{}, 37 Period{now.Add(-90 * time.Minute), now.Add(-70 * time.Minute)}, 38 Cost{}, 39 ErrMissingData, 40 }, 41 { // Period starting and ending after data. 42 time.Time{}, 43 Period{now.Add(3*time.Hour + 1*time.Minute), now.Add(4 * time.Hour)}, 44 Cost{}, 45 ErrMissingData, 46 }, 47 { // Period starting before data but ending within. 48 time.Time{}, 49 Period{now.Add(-90 * time.Minute), now.Add(-30 * time.Minute)}, 50 Cost{ 51 Period{now.Add(-60 * time.Minute), now.Add(-30 * time.Minute)}, 52 60 * 30.0 / 60.0, 53 }, 54 nil, 55 }, 56 { // Period starting within data and going beyond. 57 terminated, 58 Period{now.Add(2 * time.Hour), now.Add(4 * time.Hour)}, 59 Cost{ 60 Period{now.Add(2 * time.Hour), terminated}, 61 90*1.0/62.0 + 120 + 90, 62 }, 63 nil, 64 }, 65 { // Period starting within data and going beyond with no terminated 66 time.Time{}, 67 Period{now.Add(2 * time.Hour), now.Add(4 * time.Hour)}, 68 Cost{ 69 Period{now.Add(2 * time.Hour), now.Add(4 * time.Hour)}, 70 90*1.0/62.0 + 120 + 90, 71 }, 72 nil, 73 }, 74 { // Period starting exactly at some timestamp and ending within its period. 75 time.Time{}, 76 Period{now, now.Add(5 * time.Minute)}, 77 Cost{ 78 Period{now, now.Add(5 * time.Minute)}, 79 120 * 5.0 / 59.0, 80 }, 81 nil, 82 }, 83 { // Period starting and within a single time period. 84 time.Time{}, 85 Period{now.Add(1 * time.Minute), now.Add(6 * time.Minute)}, 86 Cost{ 87 Period{now.Add(1 * time.Minute), now.Add(6 * time.Minute)}, 88 120 * 5.0 / 59.0, 89 }, 90 nil, 91 }, 92 { // Period starting exactly at some timestamp and spanning more than one. 93 time.Time{}, 94 Period{now, now.Add(80 * time.Minute)}, 95 Cost{ 96 Period{now, now.Add(80 * time.Minute)}, 97 120 + 90*21.0/62.0, 98 }, 99 nil, 100 }, 101 { // Period starting before data and ending after. 102 terminated, 103 Period{now.Add(-90 * time.Minute), now.Add(6 * time.Hour)}, 104 Cost{ 105 Period{now.Add(-60 * time.Minute), terminated}, 106 60 + 120 + 90 + 120 + 90, 107 }, 108 nil, 109 }, 110 { // Period starting before data and ending after with no terminated. 111 time.Time{}, 112 Period{now.Add(-90 * time.Minute), now.Add(6 * time.Hour)}, 113 Cost{ 114 Period{now.Add(-60 * time.Minute), now.Add(6 * time.Hour)}, 115 60 + 120 + 90 + 120 + 90, 116 }, 117 nil, 118 }, 119 { // Period starting within data but ending within last period before instance end time. 120 terminated, 121 Period{now.Add(-90 * time.Minute), now.Add(3*time.Hour + 15*time.Minute)}, 122 Cost{ 123 Period{now.Add(-60 * time.Minute), now.Add(3*time.Hour + 15*time.Minute)}, 124 60 + 120 + 90 + 120 + 90*15/30.0, 125 }, 126 nil, 127 }, 128 { // Period starting within data but ending within last period with no terminated. 129 time.Time{}, 130 Period{now.Add(-90 * time.Minute), now.Add(3*time.Hour + 15*time.Minute)}, 131 Cost{ 132 Period{now.Add(-60 * time.Minute), now.Add(3*time.Hour + 15*time.Minute)}, 133 60 + 120 + 90 + 120 + 90, 134 }, 135 nil, 136 }, 137 } { 138 c, err := q.Query(iid, tt.p, tt.iet) 139 if tt.wantE != nil { 140 if got, want := err, tt.wantE; got != want { 141 t.Errorf("[%d] got %v, want %v", i, got, want) 142 } 143 continue 144 } 145 if err != nil { 146 t.Error(err) 147 continue 148 } 149 if got, want := c, tt.c; got != want { 150 t.Errorf("[%d[ got %v, want %v", i, got, want) 151 } 152 } 153 }