@@ -6089,7 +6089,7 @@ func TestCuttingNewHeadChunks(t *testing.T) {
6089
6089
}
6090
6090
}
6091
6091
6092
- func TestAppendDuplicates (t * testing.T ) {
6092
+ func TestAppendQuietZeroDuplicates (t * testing.T ) {
6093
6093
ts := int64 (1695209650 )
6094
6094
lbls := labels .FromStrings ("foo" , "bar" )
6095
6095
h , _ := newTestHead (t , DefaultBlockDuration , wlog .CompressionNone , false )
@@ -6134,6 +6134,77 @@ func TestAppendDuplicates(t *testing.T) {
6134
6134
require .Equal (t , expectedSamples , result [`{foo="bar"}` ]) // Same expectedSamples as before.
6135
6135
}
6136
6136
6137
+ func TestQuietZeroWALReplay (t * testing.T ) {
6138
+ ts := int64 (1695209650 )
6139
+ lbls := labels .FromStrings ("foo" , "bar" )
6140
+ h , w := newTestHead (t , DefaultBlockDuration , wlog .CompressionNone , false )
6141
+
6142
+ a := h .Appender (context .Background ())
6143
+ _ , err := a .Append (0 , lbls , ts , 42.0 )
6144
+ require .NoError (t , err )
6145
+ _ , err = a .Append (0 , lbls , ts , 42.0 ) // Exactly the same value.
6146
+ require .NoError (t , err )
6147
+ _ , err = a .Append (0 , lbls , ts , math .Float64frombits (value .QuietZeroNaN )) // Should be a no-op.
6148
+ require .NoError (t , err )
6149
+ _ , err = a .Append (0 , lbls , ts + 10 , math .Float64frombits (value .QuietZeroNaN )) // This is at a different timestamp so should append a real zero.
6150
+ require .NoError (t , err )
6151
+ _ , err = a .Append (0 , lbls , ts + 5 , math .Float64frombits (value .QuietZeroNaN )) // This is out-of-order, so should be dropped.
6152
+ require .NoError (t , err )
6153
+ require .NoError (t , a .Commit ())
6154
+
6155
+ result , err := queryHead (t , h , math .MinInt64 , math .MaxInt64 , labels.Label {Name : "foo" , Value : "bar" })
6156
+ require .NoError (t , err )
6157
+ expectedSamples := []chunks.Sample {
6158
+ sample {t : ts , f : 42.0 },
6159
+ sample {t : ts + 10 , f : 0 },
6160
+ }
6161
+ require .Equal (t , expectedSamples , result [`{foo="bar"}` ])
6162
+
6163
+ require .NoError (t , h .Close ())
6164
+
6165
+ // Next we replay the WAL by creating a new head and then verify that previous samples are there as we expect them.
6166
+ w , err = wlog .New (nil , nil , w .Dir (), wlog .CompressionNone )
6167
+ require .NoError (t , err )
6168
+ opts := DefaultHeadOptions ()
6169
+ opts .ChunkRange = 1000
6170
+ opts .ChunkDirRoot = w .Dir ()
6171
+ h , err = NewHead (nil , nil , w , nil , opts , nil )
6172
+ require .NoError (t , err )
6173
+ require .NoError (t , h .Init (0 ))
6174
+ defer func () {
6175
+ require .NoError (t , h .Close ())
6176
+ }()
6177
+
6178
+ result , err = queryHead (t , h , math .MinInt64 , math .MaxInt64 , labels.Label {Name : "foo" , Value : "bar" })
6179
+ require .NoError (t , err )
6180
+ require .Equal (t , expectedSamples , result [`{foo="bar"}` ])
6181
+
6182
+ // For correctness, we also verify that the WAL contains the expected records.
6183
+ recs := readTestWAL (t , h .wal .Dir ())
6184
+ require .NotEmpty (t , recs , "WAL should contain records" )
6185
+
6186
+ if s , ok := recs [0 ].([]record.RefSeries ); ok {
6187
+ require .Len (t , s , 1 )
6188
+ require .Equal (t , labels.Label {Name : "foo" , Value : "bar" }, s [0 ].Labels [0 ])
6189
+ } else {
6190
+ t .Fatalf ("unexpected record type: %T" , recs [0 ])
6191
+ }
6192
+
6193
+ if samples , ok := recs [1 ].([]record.RefSample ); ok {
6194
+ require .Len (t , samples , 5 )
6195
+ require .Equal (t , record.RefSample {Ref : 1 , T : ts , V : 42.0 }, samples [0 ])
6196
+ require .Equal (t , record.RefSample {Ref : 1 , T : ts , V : 42.0 }, samples [1 ])
6197
+ require .True (t , math .IsNaN (samples [2 ].V ))
6198
+ require .Equal (t , ts , samples [2 ].T )
6199
+ require .True (t , math .IsNaN (samples [3 ].V ))
6200
+ require .Equal (t , ts + 10 , samples [3 ].T )
6201
+ require .True (t , math .IsNaN (samples [4 ].V ))
6202
+ require .Equal (t , ts + 5 , samples [4 ].T )
6203
+ } else {
6204
+ t .Fatalf ("unexpected record type: %T" , recs [1 ])
6205
+ }
6206
+ }
6207
+
6137
6208
// TestHeadDetectsDuplicateSampleAtSizeLimit tests a regression where a duplicate sample
6138
6209
// is appended to the head, right when the head chunk is at the size limit.
6139
6210
// The test adds all samples as duplicate, thus expecting that the result has
0 commit comments