@@ -12,11 +12,13 @@ import (
12
12
"testing"
13
13
"time"
14
14
15
+ "github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
15
16
"github.com/cockroachdb/cockroach/pkg/keys"
16
17
"github.com/cockroachdb/cockroach/pkg/roachpb"
17
18
"github.com/cockroachdb/cockroach/pkg/settings/cluster"
18
19
"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
19
20
"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
21
+ "github.com/cockroachdb/cockroach/pkg/util/hlc"
20
22
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
21
23
"github.com/cockroachdb/cockroach/pkg/util/log"
22
24
"github.com/stretchr/testify/require"
@@ -228,19 +230,29 @@ func runProcessorAndWait(t *testing.T, proc *inspectProcessor, expectErr bool) {
228
230
229
231
// makeProcessor will create an inspect processor for test.
230
232
func makeProcessor (
231
- t * testing.T , checkFactory inspectCheckFactory , src spanSource , concurrency int ,
233
+ t * testing.T ,
234
+ checkFactory inspectCheckFactory ,
235
+ src spanSource ,
236
+ concurrency int ,
237
+ asOf hlc.Timestamp ,
232
238
) (* inspectProcessor , * testIssueCollector ) {
233
239
t .Helper ()
240
+ clock := hlc .NewClockForTesting (nil )
234
241
logger := & testIssueCollector {}
235
242
proc := & inspectProcessor {
236
- spec : execinfrapb.InspectSpec {},
243
+ spec : execinfrapb.InspectSpec {
244
+ InspectDetails : jobspb.InspectDetails {
245
+ AsOf : asOf ,
246
+ },
247
+ },
237
248
checkFactories : []inspectCheckFactory {checkFactory },
238
249
cfg : & execinfra.ServerConfig {
239
250
Settings : cluster .MakeTestingClusterSettings (),
240
251
},
241
252
spanSrc : src ,
242
253
logger : logger ,
243
254
concurrency : concurrency ,
255
+ clock : clock ,
244
256
}
245
257
return proc , logger
246
258
}
@@ -318,12 +330,12 @@ func TestInspectProcessor_ControlFlow(t *testing.T) {
318
330
319
331
for _ , tc := range tests {
320
332
t .Run (tc .desc , func (t * testing.T ) {
321
- factory := func () inspectCheck {
333
+ factory := func (asOf hlc. Timestamp ) inspectCheck {
322
334
return & testingInspectCheck {
323
335
configs : tc .configs ,
324
336
}
325
337
}
326
- proc , _ := makeProcessor (t , factory , tc .spanSrc , len (tc .configs ))
338
+ proc , _ := makeProcessor (t , factory , tc .spanSrc , len (tc .configs ), hlc. Timestamp {} )
327
339
runProcessorAndWait (t , proc , tc .expectErr )
328
340
})
329
341
}
@@ -337,7 +349,7 @@ func TestInspectProcessor_EmitIssues(t *testing.T) {
337
349
mode : spanModeNormal ,
338
350
maxSpans : 1 ,
339
351
}
340
- factory := func () inspectCheck {
352
+ factory := func (asOf hlc. Timestamp ) inspectCheck {
341
353
return & testingInspectCheck {
342
354
configs : []testingCheckConfig {
343
355
{
@@ -350,9 +362,78 @@ func TestInspectProcessor_EmitIssues(t *testing.T) {
350
362
},
351
363
}
352
364
}
353
- proc , logger := makeProcessor (t , factory , spanSrc , 1 )
365
+ proc , logger := makeProcessor (t , factory , spanSrc , 1 , hlc. Timestamp {} )
354
366
355
367
runProcessorAndWait (t , proc , true /* expectErr */ )
356
368
357
369
require .Equal (t , 2 , logger .numIssuesFound ())
358
370
}
371
+
372
+ func TestInspectProcessor_AsOfTime (t * testing.T ) {
373
+ defer leaktest .AfterTest (t )()
374
+ defer log .Scope (t ).Close (t )
375
+
376
+ tests := []struct {
377
+ name string
378
+ asOf hlc.Timestamp
379
+ verifyTimestamp func (t * testing.T , actualTime time.Time , capturedTimestamp hlc.Timestamp , testStartTime time.Time )
380
+ }{
381
+ {
382
+ name : "empty timestamp uses clock time" ,
383
+ asOf : hlc.Timestamp {}, // Empty timestamp
384
+ verifyTimestamp : func (t * testing.T , actualTime time.Time , capturedTimestamp hlc.Timestamp , testStartTime time.Time ) {
385
+ // Verify that the AOST time in the issue is >= the test start time
386
+ require .True (t , actualTime .After (testStartTime ) || actualTime .Equal (testStartTime ),
387
+ "AOST time (%v) should be >= test start time (%v)" , actualTime , testStartTime )
388
+ // Also verify the timestamp was not empty
389
+ require .False (t , capturedTimestamp .IsEmpty (),
390
+ "Captured timestamp should not be empty when AsOf is not specified" )
391
+ },
392
+ },
393
+ {
394
+ name : "specific timestamp is preserved" ,
395
+ asOf : hlc.Timestamp {WallTime : 12345 },
396
+ verifyTimestamp : func (t * testing.T , actualTime time.Time , capturedTimestamp hlc.Timestamp , testStartTime time.Time ) {
397
+ // Verify that the exact timestamp is preserved
398
+ require .Equal (t , hlc.Timestamp {WallTime : 12345 }.GoTime (), actualTime )
399
+ },
400
+ },
401
+ }
402
+
403
+ for _ , tc := range tests {
404
+ t .Run (tc .name , func (t * testing.T ) {
405
+ spanSrc := & testingSpanSource {
406
+ mode : spanModeNormal ,
407
+ maxSpans : 1 ,
408
+ }
409
+
410
+ // Record start time before creating the processor
411
+ testStartTime := time .Now ()
412
+
413
+ var capturedTimestamp hlc.Timestamp
414
+ factory := func (asOf hlc.Timestamp ) inspectCheck {
415
+ capturedTimestamp = asOf
416
+ return & testingInspectCheck {
417
+ configs : []testingCheckConfig {
418
+ {
419
+ mode : checkModeNone ,
420
+ issues : []* inspectIssue {
421
+ {ErrorType : "test_error" , PrimaryKey : "pk1" , AOST : asOf .GoTime ()},
422
+ },
423
+ },
424
+ },
425
+ }
426
+ }
427
+
428
+ proc , logger := makeProcessor (t , factory , spanSrc , 1 , tc .asOf )
429
+
430
+ runProcessorAndWait (t , proc , true /* expectErr */ )
431
+
432
+ require .Equal (t , 1 , logger .numIssuesFound ())
433
+
434
+ // Run the test-specific timestamp verification
435
+ actualTime := logger .issue (0 ).AOST
436
+ tc .verifyTimestamp (t , actualTime , capturedTimestamp , testStartTime )
437
+ })
438
+ }
439
+ }
0 commit comments