From 005965f537875042f506e897e2a1604363ac0363 Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Thu, 19 Mar 2026 10:18:48 +0100 Subject: [PATCH 1/2] test: add spec test for duplicate variant materialization assignments Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/resolver_spec_tests.rs | 3 ++ .../test-payloads/resolver-spec/state.json | 35 +++++++++++++++++++ .../test-payloads/resolver-spec/tests.json | 32 +++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/confidence-resolver/src/resolver_spec_tests.rs b/confidence-resolver/src/resolver_spec_tests.rs index c2641103..8c275289 100644 --- a/confidence-resolver/src/resolver_spec_tests.rs +++ b/confidence-resolver/src/resolver_spec_tests.rs @@ -641,3 +641,6 @@ spec_test!(combined_both_match); spec_test!(combined_only_attr); spec_test!(combined_only_mat); spec_test!(combined_neither); + +// Materialization: duplicate variant assignments +spec_test!(mat_same_variant_two_assignments_returns_correct_assignment_id); diff --git a/confidence-resolver/test-payloads/resolver-spec/state.json b/confidence-resolver/test-payloads/resolver-spec/state.json index c9c9519b..41b995c4 100644 --- a/confidence-resolver/test-payloads/resolver-spec/state.json +++ b/confidence-resolver/test-payloads/resolver-spec/state.json @@ -2031,6 +2031,41 @@ } } ] + }, + "flags/mat-same-variant-flag": { + "name": "flags/mat-same-variant-flag", + "state": "ACTIVE", + "clients": ["clients/test-client"], + "variants": [ + { "name": "on", "value": { "enabled": true } } + ], + "rules": [ + { + "name": "flags/mat-same-variant-flag/rules/rule1", + "segment": "segments/country-se", + "enabled": true, + "targetingKeySelector": "targeting_key", + "materializationSpec": { + "readMaterialization": "materializations/mat1", + "writeMaterialization": "materializations/mat1" + }, + "assignmentSpec": { + "bucketCount": 1000, + "assignments": [ + { + "assignmentId": "a1", + "variant": { "variant": "on" }, + "bucketRanges": [{ "lower": 0, "upper": 500 }] + }, + { + "assignmentId": "a2", + "variant": { "variant": "on" }, + "bucketRanges": [{ "lower": 500, "upper": 1000 }] + } + ] + } + } + ] } }, "segments": { diff --git a/confidence-resolver/test-payloads/resolver-spec/tests.json b/confidence-resolver/test-payloads/resolver-spec/tests.json index 57279dac..5758607d 100644 --- a/confidence-resolver/test-payloads/resolver-spec/tests.json +++ b/confidence-resolver/test-payloads/resolver-spec/tests.json @@ -3891,5 +3891,37 @@ "expectError": null } } + }, + { + "name": "mat_same_variant_two_assignments_returns_correct_assignment_id", + "resolveRequest": { + "flags": ["flags/mat-same-variant-flag"], + "evaluationContext": { "targeting_key": "user1", "country": "SE" }, + "clientSecret": "test-secret" + }, + "materializations": { + "user1": { + "materializations/mat1": { + "isUnitInMaterialization": true, + "ruleToVariant": { + "flags/mat-same-variant-flag/rules/rule1": "on" + } + } + } + }, + "expectedResult": { + "general": { + "resolvedFlags": [ + { + "flag": "flags/mat-same-variant-flag", + "reason": "RESOLVE_REASON_MATCH", + "variant": "on", + "value": { "enabled": true }, + "shouldApply": true + } + ], + "expectError": null + } + } } ] From 8d2ffbc248952f2cac0a418be85b982372e5d00a Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Thu, 19 Mar 2026 11:37:01 +0100 Subject: [PATCH 2/2] test: add assignmentId assertion to spec test runner Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/resolver_spec_tests.rs | 32 +++++++++++++++++++ .../test-payloads/resolver-spec/tests.json | 3 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/confidence-resolver/src/resolver_spec_tests.rs b/confidence-resolver/src/resolver_spec_tests.rs index 8c275289..f6dca833 100644 --- a/confidence-resolver/src/resolver_spec_tests.rs +++ b/confidence-resolver/src/resolver_spec_tests.rs @@ -120,6 +120,7 @@ struct SpecResolvedFlag { variant: String, value: Option, should_apply: Option, + assignment_id: Option, } // --------------------------------------------------------------------------- @@ -424,6 +425,37 @@ fn run_spec_test(state: &ResolverState, test_case: &SpecTestCase) { test_case.name, expected_flag.flag, expected_should_apply, actual_should_apply, ); } + + // assignmentId assertion (from resolve token) + if let Some(expected_assignment_id) = &expected_flag.assignment_id { + let token = resolver + .decrypt_resolve_token(&resolve_response.resolve_token) + .unwrap_or_else(|e| { + panic!( + "[{}] Failed to decrypt resolve token: {}", + test_case.name, e, + ) + }); + match token.resolve_token { + Some(flags_resolver::resolve_token::ResolveToken::TokenV1(token_v1)) => { + let assigned = token_v1.assignments.get(&expected_flag.flag).unwrap_or_else(|| { + panic!( + "[{}] Flag '{}' not found in resolve token assignments", + test_case.name, expected_flag.flag, + ) + }); + assert_eq!( + &assigned.assignment_id, expected_assignment_id, + "[{}] assignmentId mismatch for flag '{}'", + test_case.name, expected_flag.flag, + ); + } + _ => panic!( + "[{}] Expected TokenV1 in resolve token", + test_case.name, + ), + } + } } } diff --git a/confidence-resolver/test-payloads/resolver-spec/tests.json b/confidence-resolver/test-payloads/resolver-spec/tests.json index 5758607d..805aab60 100644 --- a/confidence-resolver/test-payloads/resolver-spec/tests.json +++ b/confidence-resolver/test-payloads/resolver-spec/tests.json @@ -3917,7 +3917,8 @@ "reason": "RESOLVE_REASON_MATCH", "variant": "on", "value": { "enabled": true }, - "shouldApply": true + "shouldApply": true, + "assignmentId": "a2" } ], "expectError": null