mockserver-client 7.2.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +61 -1
- data/lib/mockserver/a2a.rb +529 -0
- data/lib/mockserver/client.rb +504 -0
- data/lib/mockserver/models.rb +270 -16
- data/lib/mockserver/version.rb +1 -1
- data/lib/mockserver-client.rb +1 -0
- metadata +3 -2
data/lib/mockserver/models.rb
CHANGED
|
@@ -2368,39 +2368,262 @@ module MockServer
|
|
|
2368
2368
|
end
|
|
2369
2369
|
end
|
|
2370
2370
|
|
|
2371
|
-
#
|
|
2372
|
-
#
|
|
2373
|
-
#
|
|
2374
|
-
# the
|
|
2371
|
+
# A declarative named load shape that expands into ordinary {LoadStage} stages.
|
|
2372
|
+
# Set this as a {LoadProfile}'s +shape+ instead of an explicit +stages+ list;
|
|
2373
|
+
# only the parameters its +type+ needs are read. +type+ is one of +SPIKE+,
|
|
2374
|
+
# +STAIRS+ or +RAMP_HOLD+; +metric+ (+VU+ or +RATE+) selects what the shape
|
|
2375
|
+
# drives.
|
|
2376
|
+
class LoadShape
|
|
2377
|
+
attr_accessor :type, :metric, :curve, :baseline, :peak, :ramp_up_millis,
|
|
2378
|
+
:hold_millis, :ramp_down_millis, :recovery_hold_millis,
|
|
2379
|
+
:start, :step, :steps, :step_duration_millis, :target, :ramp_millis
|
|
2380
|
+
|
|
2381
|
+
def initialize(type:, metric: nil, curve: nil, baseline: nil, peak: nil,
|
|
2382
|
+
ramp_up_millis: nil, hold_millis: nil, ramp_down_millis: nil,
|
|
2383
|
+
recovery_hold_millis: nil, start: nil, step: nil, steps: nil,
|
|
2384
|
+
step_duration_millis: nil, target: nil, ramp_millis: nil)
|
|
2385
|
+
@type = type
|
|
2386
|
+
@metric = metric
|
|
2387
|
+
@curve = curve
|
|
2388
|
+
@baseline = baseline
|
|
2389
|
+
@peak = peak
|
|
2390
|
+
@ramp_up_millis = ramp_up_millis
|
|
2391
|
+
@hold_millis = hold_millis
|
|
2392
|
+
@ramp_down_millis = ramp_down_millis
|
|
2393
|
+
@recovery_hold_millis = recovery_hold_millis
|
|
2394
|
+
@start = start
|
|
2395
|
+
@step = step
|
|
2396
|
+
@steps = steps
|
|
2397
|
+
@step_duration_millis = step_duration_millis
|
|
2398
|
+
@target = target
|
|
2399
|
+
@ramp_millis = ramp_millis
|
|
2400
|
+
end
|
|
2401
|
+
|
|
2402
|
+
def to_h
|
|
2403
|
+
MockServer.strip_none({
|
|
2404
|
+
'type' => @type,
|
|
2405
|
+
'metric' => @metric,
|
|
2406
|
+
'curve' => @curve,
|
|
2407
|
+
'baseline' => @baseline,
|
|
2408
|
+
'peak' => @peak,
|
|
2409
|
+
'rampUpMillis' => @ramp_up_millis,
|
|
2410
|
+
'holdMillis' => @hold_millis,
|
|
2411
|
+
'rampDownMillis' => @ramp_down_millis,
|
|
2412
|
+
'recoveryHoldMillis' => @recovery_hold_millis,
|
|
2413
|
+
'start' => @start,
|
|
2414
|
+
'step' => @step,
|
|
2415
|
+
'steps' => @steps,
|
|
2416
|
+
'stepDurationMillis' => @step_duration_millis,
|
|
2417
|
+
'target' => @target,
|
|
2418
|
+
'rampMillis' => @ramp_millis
|
|
2419
|
+
})
|
|
2420
|
+
end
|
|
2421
|
+
|
|
2422
|
+
def self.from_hash(data)
|
|
2423
|
+
return nil if data.nil?
|
|
2424
|
+
|
|
2425
|
+
new(
|
|
2426
|
+
type: data['type'],
|
|
2427
|
+
metric: data['metric'],
|
|
2428
|
+
curve: data['curve'],
|
|
2429
|
+
baseline: data['baseline'],
|
|
2430
|
+
peak: data['peak'],
|
|
2431
|
+
ramp_up_millis: data['rampUpMillis'],
|
|
2432
|
+
hold_millis: data['holdMillis'],
|
|
2433
|
+
ramp_down_millis: data['rampDownMillis'],
|
|
2434
|
+
recovery_hold_millis: data['recoveryHoldMillis'],
|
|
2435
|
+
start: data['start'],
|
|
2436
|
+
step: data['step'],
|
|
2437
|
+
steps: data['steps'],
|
|
2438
|
+
step_duration_millis: data['stepDurationMillis'],
|
|
2439
|
+
target: data['target'],
|
|
2440
|
+
ramp_millis: data['rampMillis']
|
|
2441
|
+
)
|
|
2442
|
+
end
|
|
2443
|
+
end
|
|
2444
|
+
|
|
2445
|
+
# The traffic-shaping profile of a load scenario: EITHER an ordered list of
|
|
2446
|
+
# {LoadStage} objects run in sequence, each holding or ramping a setpoint
|
|
2447
|
+
# (virtual users, an arrival rate, or a pause) for its duration, OR a single
|
|
2448
|
+
# named {LoadShape} that expands into stages. Set one, not both; if both are
|
|
2449
|
+
# set the explicit stages win. The total run length is the sum of the stage
|
|
2450
|
+
# durations.
|
|
2375
2451
|
class LoadProfile
|
|
2376
|
-
attr_accessor :stages
|
|
2452
|
+
attr_accessor :stages, :shape
|
|
2453
|
+
|
|
2454
|
+
def initialize(stages: nil, shape: nil)
|
|
2455
|
+
@stages = stages
|
|
2456
|
+
@shape = shape
|
|
2457
|
+
end
|
|
2458
|
+
|
|
2459
|
+
def to_h
|
|
2460
|
+
MockServer.strip_none({
|
|
2461
|
+
'stages' => @stages.nil? ? nil : @stages.map(&:to_h),
|
|
2462
|
+
'shape' => @shape&.to_h
|
|
2463
|
+
})
|
|
2464
|
+
end
|
|
2465
|
+
|
|
2466
|
+
def self.from_hash(data)
|
|
2467
|
+
return nil if data.nil?
|
|
2468
|
+
|
|
2469
|
+
stages_data = data['stages']
|
|
2470
|
+
new(
|
|
2471
|
+
stages: stages_data ? stages_data.map { |s| LoadStage.from_hash(s) } : nil,
|
|
2472
|
+
shape: LoadShape.from_hash(data['shape'])
|
|
2473
|
+
)
|
|
2474
|
+
end
|
|
2475
|
+
end
|
|
2476
|
+
|
|
2477
|
+
# A declarative cross-step capture / correlation rule: extracts a value from a
|
|
2478
|
+
# step's response and binds it to +name+, which a later step in the same
|
|
2479
|
+
# iteration can reference from its templated request fields. +source+ is one of
|
|
2480
|
+
# +BODY_JSONPATH+, +HEADER+ or +BODY_REGEX+; +expression+ drives the extraction;
|
|
2481
|
+
# +default_value+ is an optional fallback when extraction yields nothing.
|
|
2482
|
+
class LoadCapture
|
|
2483
|
+
attr_accessor :name, :source, :expression, :default_value
|
|
2377
2484
|
|
|
2378
|
-
def initialize(
|
|
2379
|
-
@
|
|
2485
|
+
def initialize(name:, source:, expression:, default_value: nil)
|
|
2486
|
+
@name = name
|
|
2487
|
+
@source = source
|
|
2488
|
+
@expression = expression
|
|
2489
|
+
@default_value = default_value
|
|
2380
2490
|
end
|
|
2381
2491
|
|
|
2382
2492
|
def to_h
|
|
2383
|
-
|
|
2493
|
+
MockServer.strip_none({
|
|
2494
|
+
'name' => @name,
|
|
2495
|
+
'source' => @source,
|
|
2496
|
+
'expression' => @expression,
|
|
2497
|
+
'defaultValue' => @default_value
|
|
2498
|
+
})
|
|
2384
2499
|
end
|
|
2385
2500
|
|
|
2386
2501
|
def self.from_hash(data)
|
|
2387
2502
|
return nil if data.nil?
|
|
2388
2503
|
|
|
2389
|
-
|
|
2390
|
-
|
|
2504
|
+
new(
|
|
2505
|
+
name: data['name'],
|
|
2506
|
+
source: data['source'],
|
|
2507
|
+
expression: data['expression'],
|
|
2508
|
+
default_value: data['defaultValue']
|
|
2509
|
+
)
|
|
2510
|
+
end
|
|
2511
|
+
end
|
|
2512
|
+
|
|
2513
|
+
# An in-run pass/fail threshold for a load scenario: a per-run +metric+ compared
|
|
2514
|
+
# with +comparator+ against +threshold+. All thresholds must hold for the run
|
|
2515
|
+
# verdict to be +PASS+; any breach makes it +FAIL+. +metric+ is one of
|
|
2516
|
+
# +LATENCY_P50+/+LATENCY_P95+/+LATENCY_P99+/+LATENCY_P999+/+ERROR_RATE+/
|
|
2517
|
+
# +THROUGHPUT_RPS+; +comparator+ is one of +LESS_THAN+/+LESS_THAN_OR_EQUAL+/
|
|
2518
|
+
# +GREATER_THAN+/+GREATER_THAN_OR_EQUAL+.
|
|
2519
|
+
class LoadThreshold
|
|
2520
|
+
attr_accessor :metric, :comparator, :threshold
|
|
2521
|
+
|
|
2522
|
+
def initialize(metric:, comparator:, threshold:)
|
|
2523
|
+
@metric = metric
|
|
2524
|
+
@comparator = comparator
|
|
2525
|
+
@threshold = threshold
|
|
2526
|
+
end
|
|
2527
|
+
|
|
2528
|
+
def to_h
|
|
2529
|
+
MockServer.strip_none({
|
|
2530
|
+
'metric' => @metric,
|
|
2531
|
+
'comparator' => @comparator,
|
|
2532
|
+
'threshold' => @threshold
|
|
2533
|
+
})
|
|
2534
|
+
end
|
|
2535
|
+
|
|
2536
|
+
def self.from_hash(data)
|
|
2537
|
+
return nil if data.nil?
|
|
2538
|
+
|
|
2539
|
+
new(
|
|
2540
|
+
metric: data['metric'],
|
|
2541
|
+
comparator: data['comparator'],
|
|
2542
|
+
threshold: data['threshold']
|
|
2543
|
+
)
|
|
2544
|
+
end
|
|
2545
|
+
end
|
|
2546
|
+
|
|
2547
|
+
# Adaptive iteration pacing (think-time) for a load scenario: a target
|
|
2548
|
+
# per-virtual-user iteration cycle time. +mode+ is one of +NONE+,
|
|
2549
|
+
# +CONSTANT_PACING+ (+value+ is the target cycle in milliseconds) or
|
|
2550
|
+
# +CONSTANT_THROUGHPUT+ (+value+ is the target iterations/second per VU).
|
|
2551
|
+
class LoadPacing
|
|
2552
|
+
attr_accessor :mode, :value
|
|
2553
|
+
|
|
2554
|
+
def initialize(mode:, value: nil)
|
|
2555
|
+
@mode = mode
|
|
2556
|
+
@value = value
|
|
2557
|
+
end
|
|
2558
|
+
|
|
2559
|
+
def to_h
|
|
2560
|
+
MockServer.strip_none({
|
|
2561
|
+
'mode' => @mode,
|
|
2562
|
+
'value' => @value
|
|
2563
|
+
})
|
|
2564
|
+
end
|
|
2565
|
+
|
|
2566
|
+
def self.from_hash(data)
|
|
2567
|
+
return nil if data.nil?
|
|
2568
|
+
|
|
2569
|
+
new(
|
|
2570
|
+
mode: data['mode'],
|
|
2571
|
+
value: data['value']
|
|
2572
|
+
)
|
|
2573
|
+
end
|
|
2574
|
+
end
|
|
2575
|
+
|
|
2576
|
+
# Parameterized test data (a data feeder) for a load scenario: an inline dataset
|
|
2577
|
+
# from which one row is selected per iteration and exposed to the templated
|
|
2578
|
+
# request. Supply EITHER +rows+ (inline list of column-name to value maps, the
|
|
2579
|
+
# primary form) OR +data+ + +format+ (raw CSV/JSON parsed server-side).
|
|
2580
|
+
# +strategy+ (+CIRCULAR+, +RANDOM+ or +SEQUENTIAL+) chooses how a row is picked.
|
|
2581
|
+
class LoadFeeder
|
|
2582
|
+
attr_accessor :rows, :data, :format, :strategy
|
|
2583
|
+
|
|
2584
|
+
def initialize(rows: nil, data: nil, format: nil, strategy: nil)
|
|
2585
|
+
@rows = rows
|
|
2586
|
+
@data = data
|
|
2587
|
+
@format = format
|
|
2588
|
+
@strategy = strategy
|
|
2589
|
+
end
|
|
2590
|
+
|
|
2591
|
+
def to_h
|
|
2592
|
+
MockServer.strip_none({
|
|
2593
|
+
'rows' => @rows,
|
|
2594
|
+
'data' => @data,
|
|
2595
|
+
'format' => @format,
|
|
2596
|
+
'strategy' => @strategy
|
|
2597
|
+
})
|
|
2598
|
+
end
|
|
2599
|
+
|
|
2600
|
+
def self.from_hash(data)
|
|
2601
|
+
return nil if data.nil?
|
|
2602
|
+
|
|
2603
|
+
new(
|
|
2604
|
+
rows: data['rows'],
|
|
2605
|
+
data: data['data'],
|
|
2606
|
+
format: data['format'],
|
|
2607
|
+
strategy: data['strategy']
|
|
2608
|
+
)
|
|
2391
2609
|
end
|
|
2392
2610
|
end
|
|
2393
2611
|
|
|
2394
2612
|
# A single step within a load scenario. Each step fires +request+ (an HttpRequest)
|
|
2395
2613
|
# against the target, optionally pausing for +think_time+ (a Delay) afterwards.
|
|
2614
|
+
# +captures+ binds values from this step's response for later steps in the same
|
|
2615
|
+
# iteration; +weight+ is the relative selection weight when the scenario's
|
|
2616
|
+
# +step_selection+ is +WEIGHTED+.
|
|
2396
2617
|
class LoadStep
|
|
2397
|
-
attr_accessor :name, :labels, :think_time, :request
|
|
2618
|
+
attr_accessor :name, :labels, :think_time, :request, :captures, :weight
|
|
2398
2619
|
|
|
2399
|
-
def initialize(request:, name: nil, labels: nil, think_time: nil)
|
|
2620
|
+
def initialize(request:, name: nil, labels: nil, think_time: nil, captures: nil, weight: nil)
|
|
2400
2621
|
@request = request
|
|
2401
2622
|
@name = name
|
|
2402
2623
|
@labels = labels
|
|
2403
2624
|
@think_time = think_time
|
|
2625
|
+
@captures = captures
|
|
2626
|
+
@weight = weight
|
|
2404
2627
|
end
|
|
2405
2628
|
|
|
2406
2629
|
def to_h
|
|
@@ -2408,18 +2631,23 @@ module MockServer
|
|
|
2408
2631
|
'name' => @name,
|
|
2409
2632
|
'labels' => @labels,
|
|
2410
2633
|
'thinkTime' => @think_time&.to_h,
|
|
2411
|
-
'request' => @request&.to_h
|
|
2634
|
+
'request' => @request&.to_h,
|
|
2635
|
+
'captures' => @captures.nil? ? nil : @captures.map(&:to_h),
|
|
2636
|
+
'weight' => @weight
|
|
2412
2637
|
})
|
|
2413
2638
|
end
|
|
2414
2639
|
|
|
2415
2640
|
def self.from_hash(data)
|
|
2416
2641
|
return nil if data.nil?
|
|
2417
2642
|
|
|
2643
|
+
captures_data = data['captures']
|
|
2418
2644
|
new(
|
|
2419
2645
|
name: data['name'],
|
|
2420
2646
|
labels: data['labels'],
|
|
2421
2647
|
think_time: Delay.from_hash(data['thinkTime']),
|
|
2422
|
-
request: HttpRequest.from_hash(data['request'])
|
|
2648
|
+
request: HttpRequest.from_hash(data['request']),
|
|
2649
|
+
captures: captures_data ? captures_data.map { |c| LoadCapture.from_hash(c) } : nil,
|
|
2650
|
+
weight: data['weight']
|
|
2423
2651
|
)
|
|
2424
2652
|
end
|
|
2425
2653
|
end
|
|
@@ -2427,11 +2655,18 @@ module MockServer
|
|
|
2427
2655
|
# A load-injection scenario: a named set of +steps+ driven by a traffic +profile+.
|
|
2428
2656
|
# +template_type+ selects the templating engine (+VELOCITY+ or +MUSTACHE+) used to
|
|
2429
2657
|
# render step requests; +max_requests+ caps the total requests issued.
|
|
2658
|
+
# +thresholds+ are in-run pass/fail checks; +abort_on_fail+/+abort_grace_millis+
|
|
2659
|
+
# control early-abort behaviour; +pacing+ shapes inter-iteration timing; +feeder+
|
|
2660
|
+
# supplies per-iteration data; +step_selection+ (+SEQUENTIAL+ or +WEIGHTED+)
|
|
2661
|
+
# controls how each iteration selects steps.
|
|
2430
2662
|
class LoadScenario
|
|
2431
|
-
attr_accessor :name, :template_type, :labels, :max_requests, :start_delay_millis,
|
|
2663
|
+
attr_accessor :name, :template_type, :labels, :max_requests, :start_delay_millis,
|
|
2664
|
+
:profile, :steps, :thresholds, :abort_on_fail, :abort_grace_millis,
|
|
2665
|
+
:pacing, :feeder, :step_selection
|
|
2432
2666
|
|
|
2433
2667
|
def initialize(name:, profile:, steps:, template_type: nil, labels: nil, max_requests: nil,
|
|
2434
|
-
start_delay_millis: nil
|
|
2668
|
+
start_delay_millis: nil, thresholds: nil, abort_on_fail: nil,
|
|
2669
|
+
abort_grace_millis: nil, pacing: nil, feeder: nil, step_selection: nil)
|
|
2435
2670
|
@name = name
|
|
2436
2671
|
@profile = profile
|
|
2437
2672
|
@steps = steps
|
|
@@ -2439,6 +2674,12 @@ module MockServer
|
|
|
2439
2674
|
@labels = labels
|
|
2440
2675
|
@max_requests = max_requests
|
|
2441
2676
|
@start_delay_millis = start_delay_millis
|
|
2677
|
+
@thresholds = thresholds
|
|
2678
|
+
@abort_on_fail = abort_on_fail
|
|
2679
|
+
@abort_grace_millis = abort_grace_millis
|
|
2680
|
+
@pacing = pacing
|
|
2681
|
+
@feeder = feeder
|
|
2682
|
+
@step_selection = step_selection
|
|
2442
2683
|
end
|
|
2443
2684
|
|
|
2444
2685
|
def to_h
|
|
@@ -2448,6 +2689,12 @@ module MockServer
|
|
|
2448
2689
|
'labels' => @labels,
|
|
2449
2690
|
'maxRequests' => @max_requests,
|
|
2450
2691
|
'startDelayMillis' => @start_delay_millis,
|
|
2692
|
+
'thresholds' => @thresholds.nil? ? nil : @thresholds.map(&:to_h),
|
|
2693
|
+
'abortOnFail' => @abort_on_fail,
|
|
2694
|
+
'abortGraceMillis' => @abort_grace_millis,
|
|
2695
|
+
'pacing' => @pacing&.to_h,
|
|
2696
|
+
'feeder' => @feeder&.to_h,
|
|
2697
|
+
'stepSelection' => @step_selection,
|
|
2451
2698
|
'profile' => @profile&.to_h,
|
|
2452
2699
|
'steps' => @steps&.map(&:to_h)
|
|
2453
2700
|
})
|
|
@@ -2457,12 +2704,19 @@ module MockServer
|
|
|
2457
2704
|
return nil if data.nil?
|
|
2458
2705
|
|
|
2459
2706
|
steps_data = data['steps']
|
|
2707
|
+
thresholds_data = data['thresholds']
|
|
2460
2708
|
new(
|
|
2461
2709
|
name: data['name'],
|
|
2462
2710
|
template_type: data['templateType'],
|
|
2463
2711
|
labels: data['labels'],
|
|
2464
2712
|
max_requests: data['maxRequests'],
|
|
2465
2713
|
start_delay_millis: data['startDelayMillis'],
|
|
2714
|
+
thresholds: thresholds_data ? thresholds_data.map { |t| LoadThreshold.from_hash(t) } : nil,
|
|
2715
|
+
abort_on_fail: data['abortOnFail'],
|
|
2716
|
+
abort_grace_millis: data['abortGraceMillis'],
|
|
2717
|
+
pacing: LoadPacing.from_hash(data['pacing']),
|
|
2718
|
+
feeder: LoadFeeder.from_hash(data['feeder']),
|
|
2719
|
+
step_selection: data['stepSelection'],
|
|
2466
2720
|
profile: LoadProfile.from_hash(data['profile']),
|
|
2467
2721
|
steps: steps_data ? steps_data.map { |s| LoadStep.from_hash(s) } : nil
|
|
2468
2722
|
)
|
data/lib/mockserver/version.rb
CHANGED
data/lib/mockserver-client.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mockserver-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.
|
|
4
|
+
version: 7.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Bloom
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: logger
|
|
@@ -91,6 +91,7 @@ files:
|
|
|
91
91
|
- Gemfile
|
|
92
92
|
- README.md
|
|
93
93
|
- lib/mockserver-client.rb
|
|
94
|
+
- lib/mockserver/a2a.rb
|
|
94
95
|
- lib/mockserver/binary_launcher.rb
|
|
95
96
|
- lib/mockserver/client.rb
|
|
96
97
|
- lib/mockserver/errors.rb
|