Skip to content

Commit 0e0ea8c

Browse files
authored
allow 0 rps schedules (#2252)
1 parent b5fb519 commit 0e0ea8c

File tree

3 files changed

+54
-54
lines changed

3 files changed

+54
-54
lines changed

wasp/schedule.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ func Plain(from int64, duration time.Duration) []*Segment {
2727
// Each Segment has a duration equal to the total duration divided by the number of steps.
2828
// Use this function to create uniformly distributed segments over a specified time period.
2929
func Steps(from, increase int64, steps int, duration time.Duration) []*Segment {
30+
if from == 0 {
31+
from = 1
32+
}
33+
if steps == 0 {
34+
panic("steps can't be 0 in wasp.Steps schedule")
35+
}
3036
segments := make([]*Segment, 0)
3137
perStepDuration := duration / time.Duration(steps)
3238
for i := 0; i < steps; i++ {

wasp/wasp.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ var (
3838
ErrTeardown = errors.New("generator request teardown error")
3939
ErrStartFrom = errors.New("from must be > 0")
4040
ErrInvalidSegmentDuration = errors.New("SegmentDuration must be defined")
41-
ErrMissingSegmentType = errors.New("Segment Type myst be set")
41+
ErrMissingSegmentType = errors.New("Segment Type must be set")
4242
ErrNoGun = errors.New("rps load scheduleSegments selected but gun implementation is nil")
4343
ErrNoVU = errors.New("vu load scheduleSegments selected but vu implementation is nil")
4444
ErrInvalidLabels = errors.New("invalid Loki labels, labels should be [a-z][A-Z][0-9] and _")
@@ -125,7 +125,7 @@ type Segment struct {
125125
// It returns an error if the starting point is non-positive or the duration is zero.
126126
// Use it to ensure the Segment is properly configured before processing.
127127
func (ls *Segment) Validate() error {
128-
if ls.From <= 0 {
128+
if ls.From < 0 {
129129
return ErrStartFrom
130130
}
131131
if ls.Duration == 0 {
@@ -476,6 +476,12 @@ func (g *Generator) processSegment() bool {
476476
g.currentSegment = g.scheduleSegments[g.stats.CurrentSegment.Load()]
477477
g.currentSegmentMu.Unlock()
478478
g.stats.CurrentSegment.Add(1)
479+
if g.currentSegment.From == 0 {
480+
g.currentSegment.From = 1
481+
g.Pause()
482+
} else {
483+
g.Resume()
484+
}
479485
g.currentSegment.StartTime = time.Now()
480486
switch g.Cfg.LoadType {
481487
case RPS:

wasp/wasp_test.go

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -365,12 +365,8 @@ func TestSmokeCancelledByDeadlineWait(t *testing.T) {
365365
})
366366
require.NoError(t, err)
367367
gen.Run(false)
368-
before := time.Now()
369368
_, failed := gen.Wait()
370-
after := time.Now()
371-
elapsed := after.Sub(before)
372-
// execution time + last request
373-
require.Greater(t, elapsed, 1050*time.Millisecond)
369+
374370
require.Equal(t, false, failed)
375371
stats := gen.Stats()
376372
require.GreaterOrEqual(t, stats.Success.Load(), int64(2))
@@ -388,36 +384,6 @@ func TestSmokeCancelledByDeadlineWait(t *testing.T) {
388384
require.Empty(t, gen.Errors())
389385
}
390386

391-
func TestSmokeCancelledBeforeDeadline(t *testing.T) {
392-
t.Parallel()
393-
gen, err := NewGenerator(&Config{
394-
T: t,
395-
LoadType: RPS,
396-
Schedule: Plain(1, 40*time.Millisecond),
397-
Gun: NewMockGun(&MockGunConfig{
398-
CallSleep: 50 * time.Millisecond,
399-
}),
400-
})
401-
require.NoError(t, err)
402-
gen.Run(false)
403-
before := time.Now()
404-
time.Sleep(10 * time.Millisecond)
405-
_, failed := gen.Stop()
406-
after := time.Now()
407-
elapsed := after.Sub(before)
408-
409-
require.Greater(t, elapsed, 1050*time.Millisecond)
410-
require.Equal(t, true, failed)
411-
stats := gen.Stats()
412-
require.GreaterOrEqual(t, stats.Success.Load(), int64(1))
413-
require.Equal(t, stats.CurrentRPS.Load(), int64(1))
414-
415-
okData, _, failResponses := convertResponsesData(gen)
416-
require.Equal(t, okData[0], "successCallData")
417-
require.Empty(t, failResponses)
418-
require.Empty(t, gen.Errors())
419-
}
420-
421387
func TestStopOnFirstFailure(t *testing.T) {
422388
t.Parallel()
423389
gen, err := NewGenerator(&Config{
@@ -449,13 +415,13 @@ func TestSmokeStaticRPSSchedulePrecision(t *testing.T) {
449415
require.NoError(t, err)
450416
_, failed := gen.Run(true)
451417
require.Equal(t, false, failed)
452-
require.GreaterOrEqual(t, gen.Stats().Success.Load(), int64(950))
418+
require.GreaterOrEqual(t, gen.Stats().Success.Load(), int64(980))
453419
require.LessOrEqual(t, gen.Stats().Success.Load(), int64(1010))
454420
require.Equal(t, gen.Stats().Failed.Load(), int64(0))
455421
require.Equal(t, gen.Stats().CallTimeout.Load(), int64(0))
456422

457423
okData, _, failResponses := convertResponsesData(gen)
458-
require.GreaterOrEqual(t, len(okData), 950)
424+
require.GreaterOrEqual(t, len(okData), 980)
459425
require.LessOrEqual(t, len(okData), 1010)
460426
require.Empty(t, failResponses)
461427
require.Empty(t, gen.Errors())
@@ -475,14 +441,14 @@ func TestSmokeCustomUnitPrecision(t *testing.T) {
475441
_, failed := gen.Run(true)
476442
require.Equal(t, false, failed)
477443
stats := gen.Stats()
478-
require.GreaterOrEqual(t, stats.Success.Load(), int64(4950))
444+
require.GreaterOrEqual(t, stats.Success.Load(), int64(4970))
479445
require.LessOrEqual(t, stats.Success.Load(), int64(5010))
480446
require.Equal(t, stats.Failed.Load(), int64(0))
481447
require.Equal(t, stats.CallTimeout.Load(), int64(0))
482448
require.Equal(t, stats.CurrentTimeUnit, gen.Cfg.RateLimitUnitDuration.Nanoseconds())
483449

484450
okData, _, failResponses := convertResponsesData(gen)
485-
require.GreaterOrEqual(t, len(okData), 4950)
451+
require.GreaterOrEqual(t, len(okData), 4970)
486452
require.LessOrEqual(t, len(okData), 5010)
487453
require.Empty(t, failResponses)
488454
require.Empty(t, gen.Errors())
@@ -501,13 +467,13 @@ func TestSmokeStaticRPSScheduleIsNotBlocking(t *testing.T) {
501467
require.NoError(t, err)
502468
_, failed := gen.Run(true)
503469
require.Equal(t, false, failed)
504-
require.GreaterOrEqual(t, gen.Stats().Success.Load(), int64(950))
470+
require.GreaterOrEqual(t, gen.Stats().Success.Load(), int64(980))
505471
require.LessOrEqual(t, gen.Stats().Success.Load(), int64(1010))
506472
require.Equal(t, gen.Stats().Failed.Load(), int64(0))
507473
require.Equal(t, gen.Stats().CallTimeout.Load(), int64(0))
508474

509475
okData, _, failResponses := convertResponsesData(gen)
510-
require.GreaterOrEqual(t, len(okData), 950)
476+
require.GreaterOrEqual(t, len(okData), 980)
511477
require.LessOrEqual(t, len(okData), 1010)
512478
require.Empty(t, failResponses)
513479
require.Empty(t, gen.Errors())
@@ -555,7 +521,7 @@ func TestSmokeLoadScheduleSegmentRPSDecrease(t *testing.T) {
555521

556522
func TestSmokeValidation(t *testing.T) {
557523
t.Parallel()
558-
t.Run("can't start without StartFrom var", func(t *testing.T) {
524+
t.Run("can start with 0 RPS", func(t *testing.T) {
559525
t.Parallel()
560526
_, err := NewGenerator(&Config{
561527
T: t,
@@ -565,13 +531,14 @@ func TestSmokeValidation(t *testing.T) {
565531
{
566532
From: 0,
567533
Duration: 1 * time.Second,
534+
Type: SegmentType_Plain,
568535
},
569536
},
570537
Gun: NewMockGun(&MockGunConfig{
571538
CallSleep: 10 * time.Millisecond,
572539
}),
573540
})
574-
require.Equal(t, ErrStartFrom, err)
541+
require.NoError(t, err)
575542
})
576543
t.Run("can't start with invalid segment definition", func(t *testing.T) {
577544
t.Parallel()
@@ -640,15 +607,15 @@ func TestSmokeValidation(t *testing.T) {
640607
require.Equal(t, ErrInvalidScheduleType, err)
641608
})
642609
t.Run("can't start with invalid labels", func(t *testing.T) {
643-
t.Skip("now it can start with invalid labels, need to investigate")
644610
t.Parallel()
611+
invalidUTFSymbol := string([]byte{0x80})
645612
_, err := NewGenerator(&Config{
646613
T: t,
647614
LoadType: RPS,
648615
Schedule: Plain(1, 1*time.Second),
649616
Gun: NewMockGun(&MockGunConfig{}),
650617
Labels: map[string]string{
651-
"\\.[]{}()<>*+-=!?^$|": "\\.[]{}()<>*+-=!?^$|",
618+
invalidUTFSymbol: invalidUTFSymbol,
652619
},
653620
})
654621
require.Equal(t, ErrInvalidLabels, err)
@@ -677,10 +644,10 @@ func TestSmokeVUsIncrease(t *testing.T) {
677644

678645
okData, okResponses, failResponses := convertResponsesData(gen)
679646
require.GreaterOrEqual(t, okResponses[0].Duration, 50*time.Millisecond)
680-
require.GreaterOrEqual(t, len(okResponses), 140)
681-
require.GreaterOrEqual(t, len(okData), 140)
647+
require.GreaterOrEqual(t, len(okResponses), 147)
648+
require.GreaterOrEqual(t, len(okData), 147)
682649
require.Equal(t, okResponses[0].Data.(string), "successCallData")
683-
require.Equal(t, okResponses[140].Data.(string), "successCallData")
650+
require.Equal(t, okResponses[147].Data.(string), "successCallData")
684651
require.Empty(t, failResponses)
685652
require.Empty(t, gen.Errors())
686653
}
@@ -707,10 +674,10 @@ func TestSmokeVUsDecrease(t *testing.T) {
707674

708675
okData, okResponses, failResponses := convertResponsesData(gen)
709676
require.GreaterOrEqual(t, okResponses[0].Duration, 50*time.Millisecond)
710-
require.GreaterOrEqual(t, len(okResponses), 140)
711-
require.GreaterOrEqual(t, len(okData), 140)
677+
require.GreaterOrEqual(t, len(okResponses), 147)
678+
require.GreaterOrEqual(t, len(okData), 147)
712679
require.Equal(t, okResponses[0].Data.(string), "successCallData")
713-
require.Equal(t, okResponses[140].Data.(string), "successCallData")
680+
require.Equal(t, okResponses[147].Data.(string), "successCallData")
714681
require.Empty(t, failResponses)
715682
require.Empty(t, gen.Errors())
716683
}
@@ -867,7 +834,7 @@ func TestProfiles(t *testing.T) {
867834
_, okResponses, failResponses := convertResponsesData(g1)
868835
require.Equal(t, int64(10), g1Stats.CurrentRPS.Load())
869836
require.GreaterOrEqual(t, okResponses[0].Duration, 50*time.Millisecond)
870-
require.GreaterOrEqual(t, len(okResponses), 70)
837+
require.GreaterOrEqual(t, len(okResponses), 60)
871838
require.Empty(t, failResponses)
872839
require.Empty(t, g1.Errors())
873840

@@ -1070,3 +1037,24 @@ func TestSmokeNoDuplicateRequestsOnceOnStart(t *testing.T) {
10701037
require.Empty(t, failResponses)
10711038
require.Empty(t, gen.Errors())
10721039
}
1040+
1041+
func TestZeroSchedule(t *testing.T) {
1042+
t.Parallel()
1043+
gen, err := NewGenerator(&Config{
1044+
T: t,
1045+
StatsPollInterval: 1 * time.Second,
1046+
LoadType: RPS,
1047+
Schedule: Combine(
1048+
Steps(0, 1, 10, 10*time.Second),
1049+
Plain(0, 5*time.Second),
1050+
Steps(10, -1, 10, 10*time.Second),
1051+
),
1052+
Gun: NewMockGun(&MockGunConfig{
1053+
CallSleep: 10 * time.Millisecond,
1054+
}),
1055+
})
1056+
require.NoError(t, err)
1057+
_, failed := gen.Run(true)
1058+
require.Equal(t, false, failed)
1059+
require.GreaterOrEqual(t, gen.Stats().Success.Load(), int64(5))
1060+
}

0 commit comments

Comments
 (0)