github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/util/marshal/legacy/marshal_test.go (about) 1 package marshal 2 3 import ( 4 "bytes" 5 "log" 6 "testing" 7 "time" 8 9 json "github.com/json-iterator/go" 10 "github.com/stretchr/testify/require" 11 12 loghttp "github.com/grafana/loki/pkg/loghttp/legacy" 13 "github.com/grafana/loki/pkg/logproto" 14 "github.com/grafana/loki/pkg/logqlmodel" 15 ) 16 17 // covers responses from /api/prom/query 18 var queryTests = []struct { 19 actual logqlmodel.Streams 20 expected string 21 }{ 22 { 23 logqlmodel.Streams{ 24 logproto.Stream{ 25 Entries: []logproto.Entry{ 26 { 27 Timestamp: mustParse(time.RFC3339Nano, "2019-09-13T18:32:22.380001319Z"), 28 Line: "super line", 29 }, 30 }, 31 Labels: `{test="test"}`, 32 }, 33 }, 34 `{ 35 "streams":[ 36 { 37 "labels":"{test=\"test\"}", 38 "entries":[ 39 { 40 "ts": "2019-09-13T18:32:22.380001319Z", 41 "line": "super line" 42 } 43 ] 44 } 45 ], 46 "stats" : { 47 "ingester" : { 48 "store": { 49 "chunksDownloadTime": 0, 50 "totalChunksRef": 0, 51 "totalChunksDownloaded": 0, 52 "chunk" :{ 53 "compressedBytes": 0, 54 "decompressedBytes": 0, 55 "decompressedLines": 0, 56 "headChunkBytes": 0, 57 "headChunkLines": 0, 58 "totalDuplicates": 0 59 } 60 }, 61 "totalBatches": 0, 62 "totalChunksMatched": 0, 63 "totalLinesSent": 0, 64 "totalReached": 0 65 }, 66 "querier": { 67 "store": { 68 "chunksDownloadTime": 0, 69 "totalChunksRef": 0, 70 "totalChunksDownloaded": 0, 71 "chunk" :{ 72 "compressedBytes": 0, 73 "decompressedBytes": 0, 74 "decompressedLines": 0, 75 "headChunkBytes": 0, 76 "headChunkLines": 0, 77 "totalDuplicates": 0 78 } 79 } 80 }, 81 "cache": { 82 "chunk": { 83 "entriesFound": 0, 84 "entriesRequested": 0, 85 "entriesStored": 0, 86 "bytesReceived": 0, 87 "bytesSent": 0, 88 "requests": 0 89 }, 90 "index": { 91 "entriesFound": 0, 92 "entriesRequested": 0, 93 "entriesStored": 0, 94 "bytesReceived": 0, 95 "bytesSent": 0, 96 "requests": 0 97 }, 98 "result": { 99 "entriesFound": 0, 100 "entriesRequested": 0, 101 "entriesStored": 0, 102 "bytesReceived": 0, 103 "bytesSent": 0, 104 "requests": 0 105 } 106 }, 107 "summary": { 108 "bytesProcessedPerSecond": 0, 109 "execTime": 0, 110 "linesProcessedPerSecond": 0, 111 "queueTime": 0, 112 "subqueries": 0, 113 "totalBytesProcessed":0, 114 "totalEntriesReturned":0, 115 "totalLinesProcessed":0 116 } 117 } 118 }`, 119 }, 120 } 121 122 // covers responses from /api/prom/label and /api/prom/label/{name}/values 123 var labelTests = []struct { 124 actual logproto.LabelResponse 125 expected string 126 }{ 127 { 128 logproto.LabelResponse{ 129 Values: []string{ 130 "label1", 131 "test", 132 "value", 133 }, 134 }, 135 `{"values": ["label1", "test", "value"]}`, 136 }, 137 } 138 139 // covers responses from /api/prom/tail and /api/prom/tail 140 var tailTests = []struct { 141 actual loghttp.TailResponse 142 expected string 143 }{ 144 { 145 loghttp.TailResponse{ 146 Streams: []logproto.Stream{ 147 { 148 Entries: []logproto.Entry{ 149 { 150 Timestamp: mustParse(time.RFC3339Nano, "2019-09-13T18:32:22.380001319Z"), 151 Line: "super line", 152 }, 153 }, 154 Labels: "{test=\"test\"}", 155 }, 156 }, 157 DroppedEntries: []loghttp.DroppedEntry{ 158 { 159 Timestamp: mustParse(time.RFC3339Nano, "2019-09-13T18:32:22.380001319Z"), 160 Labels: "{test=\"test\"}", 161 }, 162 }, 163 }, 164 `{ 165 "streams": [ 166 { 167 "labels": "{test=\"test\"}", 168 "entries": [ 169 { 170 "ts": "2019-09-13T18:32:22.380001319Z", 171 "line": "super line" 172 } 173 ] 174 } 175 ], 176 "dropped_entries": [ 177 { 178 "Timestamp": "2019-09-13T18:32:22.380001319Z", 179 "Labels": "{test=\"test\"}" 180 } 181 ] 182 }`, 183 }, 184 } 185 186 func Test_WriteQueryResponseJSON(t *testing.T) { 187 for i, queryTest := range queryTests { 188 var b bytes.Buffer 189 err := WriteQueryResponseJSON(logqlmodel.Result{Data: queryTest.actual}, &b) 190 require.NoError(t, err) 191 192 testJSONBytesEqual(t, []byte(queryTest.expected), b.Bytes(), "Query Test %d failed", i) 193 } 194 } 195 196 func Test_WriteLabelResponseJSON(t *testing.T) { 197 for i, labelTest := range labelTests { 198 var b bytes.Buffer 199 err := WriteLabelResponseJSON(labelTest.actual, &b) 200 require.NoError(t, err) 201 202 testJSONBytesEqual(t, []byte(labelTest.expected), b.Bytes(), "Label Test %d failed", i) 203 } 204 } 205 206 func Test_MarshalTailResponse(t *testing.T) { 207 for i, tailTest := range tailTests { 208 // marshal model object 209 bytes, err := json.Marshal(tailTest.actual) 210 require.NoError(t, err) 211 212 testJSONBytesEqual(t, []byte(tailTest.expected), bytes, "Tail Test %d failed", i) 213 } 214 } 215 216 func Test_QueryResponseMarshalLoop(t *testing.T) { 217 for i, queryTest := range queryTests { 218 var r map[string]interface{} 219 220 err := json.Unmarshal([]byte(queryTest.expected), &r) 221 require.NoError(t, err) 222 223 jsonOut, err := json.Marshal(r) 224 require.NoError(t, err) 225 226 testJSONBytesEqual(t, []byte(queryTest.expected), jsonOut, "Query Marshal Loop %d failed", i) 227 } 228 } 229 230 func Test_LabelResponseMarshalLoop(t *testing.T) { 231 for i, labelTest := range labelTests { 232 var r loghttp.LabelResponse 233 234 err := json.Unmarshal([]byte(labelTest.expected), &r) 235 require.NoError(t, err) 236 237 jsonOut, err := json.Marshal(r) 238 require.NoError(t, err) 239 240 testJSONBytesEqual(t, []byte(labelTest.expected), jsonOut, "Label Marshal Loop %d failed", i) 241 } 242 } 243 244 func Test_TailResponseMarshalLoop(t *testing.T) { 245 for i, tailTest := range tailTests { 246 var r loghttp.TailResponse 247 248 err := json.Unmarshal([]byte(tailTest.expected), &r) 249 require.NoError(t, err) 250 251 jsonOut, err := json.Marshal(r) 252 require.NoError(t, err) 253 254 testJSONBytesEqual(t, []byte(tailTest.expected), jsonOut, "Tail Marshal Loop %d failed", i) 255 } 256 } 257 258 func testJSONBytesEqual(t *testing.T, expected []byte, actual []byte, msg string, args ...interface{}) { 259 var expectedValue map[string]interface{} 260 err := json.Unmarshal(expected, &expectedValue) 261 require.NoError(t, err) 262 263 var actualValue map[string]interface{} 264 err = json.Unmarshal(actual, &actualValue) 265 require.NoError(t, err) 266 267 require.Equalf(t, expectedValue, actualValue, msg, args) 268 } 269 270 func mustParse(l string, t string) time.Time { 271 ret, err := time.Parse(l, t) 272 if err != nil { 273 log.Fatalf("Failed to parse %s", t) 274 } 275 276 return ret 277 }