github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/cloud/spotfeed/parser_test.go (about) 1 package spotfeed 2 3 import ( 4 "strings" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestParseFeedFileSuccess(t *testing.T) { 12 for _, test := range []struct { 13 name string 14 feedBlob string 15 expectedEntries []*Entry 16 }{ 17 { 18 name: "empty", 19 feedBlob: `#Version: 1.0 20 #Fields: Timestamp UsageType Operation InstanceID MyBidID MyMaxPrice MarketPrice Charge Version`, 21 expectedEntries: []*Entry{}, 22 }, 23 { 24 name: "one line", 25 feedBlob: `#Version: 1.0 26 #Fields: Timestamp UsageType Operation InstanceID MyBidID MyMaxPrice MarketPrice Charge Version 27 2020-10-29 19:35:44 UTC USW2-SpotUsage:c4.large RunInstances:SV002 i-00028539b6b1de1c0 sir-yzyi9qrm 0.100 USD 0.034 USD 0.001 USD 1`, 28 expectedEntries: []*Entry{ 29 { 30 AccountId: testAccountId, 31 Timestamp: time.Date(2020, 10, 29, 19, 35, 44, 0, time.UTC), 32 UsageType: "USW2-SpotUsage:c4.large", 33 Instance: "c4.large", 34 Operation: "RunInstances:SV002", 35 InstanceID: "i-00028539b6b1de1c0", 36 MyBidID: "sir-yzyi9qrm", 37 MyMaxPriceUSD: 0.1, 38 MarketPriceUSD: 0.034, 39 ChargeUSD: 0.001, 40 Version: 1, 41 }, 42 }, 43 }, 44 { 45 name: "m1.small", 46 feedBlob: `#Version: 1.0 47 #Fields: Timestamp UsageType Operation InstanceID MyBidID MyMaxPrice MarketPrice Charge Version 48 2020-10-29 19:38:33 UTC USW2-SpotUsage RunInstances:SV002 i-0c5a748cea172ba6b sir-7nigaazp 26.688 USD 8.006 USD 4.546 USD 1`, 49 expectedEntries: []*Entry{ 50 { 51 AccountId: testAccountId, 52 Timestamp: time.Date(2020, 10, 29, 19, 38, 33, 0, time.UTC), 53 UsageType: "USW2-SpotUsage", 54 Instance: "m1.small", 55 Operation: "RunInstances:SV002", 56 InstanceID: "i-0c5a748cea172ba6b", 57 MyBidID: "sir-7nigaazp", 58 MyMaxPriceUSD: 26.688, 59 MarketPriceUSD: 8.006, 60 ChargeUSD: 4.546, 61 Version: 1, 62 }, 63 }, 64 }, 65 { 66 name: "multiple", 67 feedBlob: `#Version: 1.0 68 #Fields: Timestamp UsageType Operation InstanceID MyBidID MyMaxPrice MarketPrice Charge Version 69 2020-10-29 19:35:44 UTC USW2-SpotUsage:c4.large RunInstances:SV002 i-00028539b6b1de1c0 sir-yzyi9qrm 0.100 USD 0.034 USD 0.001 USD 1 70 2020-10-29 19:35:05 UTC USW2-SpotUsage:c4.large RunInstances:SV002 i-0003301e05abdf3c1 sir-5d78aggq 0.100 USD 0.034 USD 0.002 USD 1 71 2020-10-29 19:35:44 UTC USW2-SpotUsage:c4.large RunInstances:SV002 i-0028e565fd6e3d37b sir-9g7ibe6n 0.100 USD 0.034 USD 0.002 USD 1`, 72 expectedEntries: []*Entry{ 73 { 74 AccountId: testAccountId, 75 Timestamp: time.Date(2020, 10, 29, 19, 35, 44, 0, time.UTC), 76 UsageType: "USW2-SpotUsage:c4.large", 77 Instance: "c4.large", 78 Operation: "RunInstances:SV002", 79 InstanceID: "i-00028539b6b1de1c0", 80 MyBidID: "sir-yzyi9qrm", 81 MyMaxPriceUSD: 0.1, 82 MarketPriceUSD: 0.034, 83 ChargeUSD: 0.001, 84 Version: 1, 85 }, 86 { 87 AccountId: testAccountId, 88 Timestamp: time.Date(2020, 10, 29, 19, 35, 05, 0, time.UTC), 89 UsageType: "USW2-SpotUsage:c4.large", 90 Instance: "c4.large", 91 Operation: "RunInstances:SV002", 92 InstanceID: "i-0003301e05abdf3c1", 93 MyBidID: "sir-5d78aggq", 94 MyMaxPriceUSD: 0.1, 95 MarketPriceUSD: 0.034, 96 ChargeUSD: 0.002, 97 Version: 1, 98 }, 99 { 100 AccountId: testAccountId, 101 Timestamp: time.Date(2020, 10, 29, 19, 35, 44, 0, time.UTC), 102 UsageType: "USW2-SpotUsage:c4.large", 103 Instance: "c4.large", 104 Operation: "RunInstances:SV002", 105 InstanceID: "i-0028e565fd6e3d37b", 106 MyBidID: "sir-9g7ibe6n", 107 MyMaxPriceUSD: 0.1, 108 MarketPriceUSD: 0.034, 109 ChargeUSD: 0.002, 110 Version: 1, 111 }, 112 }, 113 }, 114 } { 115 t.Run(test.name, func(t *testing.T) { 116 entries, err := ParseFeedFile(strings.NewReader(test.feedBlob), testAccountId) 117 require.NoError(t, err, "failed to parse feed blob") 118 require.Equal(t, test.expectedEntries, entries) 119 }) 120 } 121 } 122 123 func TestParseFeedFileNameSuccess(t *testing.T) { 124 for _, test := range []struct { 125 name string 126 fileName string 127 expectedMeta *fileMeta 128 }{ 129 { 130 "no_gzip", 131 testAccountId + ".2021-02-23-04.004.8a6d6bb8", 132 &fileMeta{ 133 nil, 134 testAccountId + ".2021-02-23-04.004.8a6d6bb8", 135 testAccountId, 136 time.Date(2021, 02, 23, 04, 0, 0, 0, time.UTC), 137 4, 138 false, 139 }, 140 }, 141 { 142 "gzip", 143 testAccountId + ".2021-02-23-04.004.8a6d6bb8.gz", 144 &fileMeta{ 145 nil, 146 testAccountId + ".2021-02-23-04.004.8a6d6bb8.gz", 147 testAccountId, 148 time.Date(2021, 02, 23, 04, 0, 0, 0, time.UTC), 149 4, 150 true, 151 }, 152 }, 153 } { 154 t.Run(test.name, func(t *testing.T) { 155 meta, err := parseFeedFileName(test.fileName) 156 require.NoError(t, err, "failed to parse feed file name") 157 require.Equal(t, test.expectedMeta, meta) 158 }) 159 } 160 } 161 162 func TestParseFeedFileNameError(t *testing.T) { 163 for _, test := range []struct { 164 name string 165 fileName string 166 expectedErr string 167 }{ 168 { 169 "fail_regex", 170 testAccountId + ".2021-02-23-04.004.8bb8", 171 "does not match", 172 }, 173 { 174 "invalid_extension", 175 testAccountId + ".2021-02-23-04.004.8a6d6bb8.zip", 176 "does not match", 177 }, 178 { 179 "invalid_date", 180 testAccountId + ".2021-13-23-04.004.8a6d6bb8.gz", 181 "failed to parse timestamp", 182 }, 183 } { 184 t.Run(test.name, func(t *testing.T) { 185 _, err := parseFeedFileName(test.fileName) 186 require.Error(t, err, "unexpected error while parsing feed file name %s but call to parseFeedFileName succeeded", test.fileName) 187 require.Contains(t, err.Error(), test.expectedErr) 188 }) 189 } 190 }