Skip to content

Commit 0213674

Browse files
Test cases added
1 parent 016fdcd commit 0213674

File tree

1 file changed

+284
-0
lines changed

1 file changed

+284
-0
lines changed
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
/**
2+
*
3+
* Copyright 2025, Optimizely and contributors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.optimizely.ab.config;
18+
19+
import com.fasterxml.jackson.databind.JsonNode;
20+
import com.fasterxml.jackson.databind.ObjectMapper;
21+
import com.optimizely.ab.config.audience.*;
22+
import org.junit.Test;
23+
import static org.junit.Assert.*;
24+
25+
import java.io.IOException;
26+
import java.util.*;
27+
28+
public class HoldoutTest {
29+
30+
// MARK: - Sample Data
31+
private static final String id = "11111";
32+
private static final String key = "background";
33+
private static final String status = Holdout.HoldoutStatus.RUNNING.toString();
34+
35+
// Create a simple Variation for testing
36+
private static Variation createVariation() {
37+
return new Variation("553339214", "house", false, Collections.<FeatureVariableUsageInstance>emptyList());
38+
}
39+
40+
// Create a simple TrafficAllocation for testing
41+
private static TrafficAllocation createTrafficAllocation() {
42+
return new TrafficAllocation("553339214", 5000);
43+
}
44+
45+
// MARK: - JSON Parsing Tests
46+
47+
@Test
48+
public void testDeserializeSuccessWithJSONValid() {
49+
// Create a Holdout object directly
50+
List<String> audienceIds = Collections.singletonList("33333");
51+
List<Variation> variations = Collections.singletonList(createVariation());
52+
List<TrafficAllocation> trafficAllocations = Collections.singletonList(createTrafficAllocation());
53+
54+
// Create a simple audience condition
55+
AudienceIdCondition audienceCondition = new AudienceIdCondition("33333");
56+
57+
Holdout holdout = new Holdout(id, key, status, audienceIds, audienceCondition,
58+
variations, Collections.<String, String>emptyMap(), trafficAllocations);
59+
60+
assertEquals(id, holdout.getId());
61+
assertEquals(key, holdout.getKey());
62+
assertEquals(Holdout.HoldoutStatus.RUNNING.toString(), holdout.getStatus());
63+
assertEquals(1, holdout.getVariations().size());
64+
assertEquals(1, holdout.getTrafficAllocation().size());
65+
assertEquals(audienceIds, holdout.getAudienceIds());
66+
assertNotNull(holdout.getAudienceConditions());
67+
assertEquals("", holdout.getLayerId()); // Always empty string
68+
}
69+
70+
@Test
71+
public void testIsActive() {
72+
// Test RUNNING status
73+
Holdout runningHoldout = new Holdout(id, key, Holdout.HoldoutStatus.RUNNING.toString(),
74+
Collections.<String>emptyList(), null, Collections.<Variation>emptyList(),
75+
Collections.<String, String>emptyMap(), Collections.<TrafficAllocation>emptyList());
76+
assertTrue(runningHoldout.isActive());
77+
assertTrue(runningHoldout.isRunning());
78+
79+
// Test DRAFT status
80+
Holdout draftHoldout = new Holdout(id, key, Holdout.HoldoutStatus.DRAFT.toString(),
81+
Collections.<String>emptyList(), null, Collections.<Variation>emptyList(),
82+
Collections.<String, String>emptyMap(), Collections.<TrafficAllocation>emptyList());
83+
assertFalse(draftHoldout.isActive());
84+
assertFalse(draftHoldout.isRunning());
85+
86+
// Test CONCLUDED status
87+
Holdout concludedHoldout = new Holdout(id, key, Holdout.HoldoutStatus.CONCLUDED.toString(),
88+
Collections.<String>emptyList(), null, Collections.<Variation>emptyList(),
89+
Collections.<String, String>emptyMap(), Collections.<TrafficAllocation>emptyList());
90+
assertFalse(concludedHoldout.isActive());
91+
assertFalse(concludedHoldout.isRunning());
92+
93+
// Test ARCHIVED status
94+
Holdout archivedHoldout = new Holdout(id, key, Holdout.HoldoutStatus.ARCHIVED.toString(),
95+
Collections.<String>emptyList(), null, Collections.<Variation>emptyList(),
96+
Collections.<String, String>emptyMap(), Collections.<TrafficAllocation>emptyList());
97+
assertFalse(archivedHoldout.isActive());
98+
assertFalse(archivedHoldout.isRunning());
99+
}
100+
101+
@Test
102+
public void testDefaultStatus() {
103+
// Create a Holdout with null status
104+
Holdout holdout = new Holdout(id, key, null, Collections.<String>emptyList(), null,
105+
Collections.<Variation>emptyList(), Collections.<String, String>emptyMap(),
106+
Collections.<TrafficAllocation>emptyList());
107+
108+
assertEquals(Holdout.HoldoutStatus.DRAFT.toString(), holdout.getStatus());
109+
}
110+
111+
// MARK: - Audience Serialization Tests
112+
113+
@Test
114+
public void testSerializeConditionScenarios() {
115+
List<Condition> audienceConditionsScenarios = getAudienceConditionsList();
116+
Map<Integer, String> expectedScenarioStringsMap = getExpectedScenariosMap();
117+
Map<String, String> audiencesMap = new HashMap<>();
118+
audiencesMap.put("1", "us");
119+
audiencesMap.put("2", "female");
120+
audiencesMap.put("3", "adult");
121+
audiencesMap.put("11", "fr");
122+
audiencesMap.put("12", "male");
123+
audiencesMap.put("13", "kid");
124+
125+
if (expectedScenarioStringsMap.size() == audienceConditionsScenarios.size()) {
126+
for (int i = 0; i < audienceConditionsScenarios.size() - 1; i++) {
127+
Holdout holdout = makeMockHoldoutWithStatus(Holdout.HoldoutStatus.RUNNING, audienceConditionsScenarios.get(i));
128+
String audiences = holdout.serializeConditions(audiencesMap);
129+
assertEquals(expectedScenarioStringsMap.get(i+1), audiences);
130+
}
131+
}
132+
}
133+
134+
public Map<Integer, String> getExpectedScenariosMap() {
135+
Map<Integer, String> expectedScenarioStringsMap = new HashMap<>();
136+
expectedScenarioStringsMap.put(1, "");
137+
expectedScenarioStringsMap.put(2, "\"us\" OR \"female\"");
138+
expectedScenarioStringsMap.put(3, "\"us\" AND \"female\" AND \"adult\"");
139+
expectedScenarioStringsMap.put(4, "NOT \"us\"");
140+
expectedScenarioStringsMap.put(5, "\"us\"");
141+
expectedScenarioStringsMap.put(6, "\"us\"");
142+
expectedScenarioStringsMap.put(7, "\"us\"");
143+
expectedScenarioStringsMap.put(8, "\"us\" OR \"female\"");
144+
expectedScenarioStringsMap.put(9, "(\"us\" OR \"female\") AND \"adult\"");
145+
expectedScenarioStringsMap.put(10, "(\"us\" OR (\"female\" AND \"adult\")) AND (\"fr\" AND (\"male\" OR \"kid\"))");
146+
expectedScenarioStringsMap.put(11, "NOT (\"us\" AND \"female\")");
147+
expectedScenarioStringsMap.put(12, "\"us\" OR \"100000\"");
148+
expectedScenarioStringsMap.put(13, "");
149+
150+
return expectedScenarioStringsMap;
151+
}
152+
153+
public List<Condition> getAudienceConditionsList() {
154+
AudienceIdCondition one = new AudienceIdCondition("1");
155+
AudienceIdCondition two = new AudienceIdCondition("2");
156+
AudienceIdCondition three = new AudienceIdCondition("3");
157+
AudienceIdCondition eleven = new AudienceIdCondition("11");
158+
AudienceIdCondition twelve = new AudienceIdCondition("12");
159+
AudienceIdCondition thirteen = new AudienceIdCondition("13");
160+
161+
// Scenario 1 - []
162+
EmptyCondition scenario1 = new EmptyCondition();
163+
164+
// Scenario 2 - ["or", "1", "2"]
165+
List<Condition> scenario2List = new ArrayList<>();
166+
scenario2List.add(one);
167+
scenario2List.add(two);
168+
OrCondition scenario2 = new OrCondition(scenario2List);
169+
170+
// Scenario 3 - ["and", "1", "2", "3"]
171+
List<Condition> scenario3List = new ArrayList<>();
172+
scenario3List.add(one);
173+
scenario3List.add(two);
174+
scenario3List.add(three);
175+
AndCondition scenario3 = new AndCondition(scenario3List);
176+
177+
// Scenario 4 - ["not", "1"]
178+
NotCondition scenario4 = new NotCondition(one);
179+
180+
// Scenario 5 - ["or", "1"]
181+
List<Condition> scenario5List = new ArrayList<>();
182+
scenario5List.add(one);
183+
OrCondition scenario5 = new OrCondition(scenario5List);
184+
185+
// Scenario 6 - ["and", "1"]
186+
List<Condition> scenario6List = new ArrayList<>();
187+
scenario6List.add(one);
188+
AndCondition scenario6 = new AndCondition(scenario6List);
189+
190+
// Scenario 7 - ["1"]
191+
AudienceIdCondition scenario7 = one;
192+
193+
// Scenario 8 - ["1", "2"]
194+
// Defaults to Or in Datafile Parsing resulting in an OrCondition
195+
OrCondition scenario8 = scenario2;
196+
197+
// Scenario 9 - ["and", ["or", "1", "2"], "3"]
198+
List<Condition> Scenario9List = new ArrayList<>();
199+
Scenario9List.add(scenario2);
200+
Scenario9List.add(three);
201+
AndCondition scenario9 = new AndCondition(Scenario9List);
202+
203+
// Scenario 10 - ["and", ["or", "1", ["and", "2", "3"]], ["and", "11, ["or", "12", "13"]]]
204+
List<Condition> scenario10List = new ArrayList<>();
205+
206+
List<Condition> or1213List = new ArrayList<>();
207+
or1213List.add(twelve);
208+
or1213List.add(thirteen);
209+
OrCondition or1213 = new OrCondition(or1213List);
210+
211+
List<Condition> and11Or1213List = new ArrayList<>();
212+
and11Or1213List.add(eleven);
213+
and11Or1213List.add(or1213);
214+
AndCondition and11Or1213 = new AndCondition(and11Or1213List);
215+
216+
List<Condition> and23List = new ArrayList<>();
217+
and23List.add(two);
218+
and23List.add(three);
219+
AndCondition and23 = new AndCondition(and23List);
220+
221+
List<Condition> or1And23List = new ArrayList<>();
222+
or1And23List.add(one);
223+
or1And23List.add(and23);
224+
OrCondition or1And23 = new OrCondition(or1And23List);
225+
226+
scenario10List.add(or1And23);
227+
scenario10List.add(and11Or1213);
228+
AndCondition scenario10 = new AndCondition(scenario10List);
229+
230+
// Scenario 11 - ["not", ["and", "1", "2"]]
231+
List<Condition> and12List = new ArrayList<>();
232+
and12List.add(one);
233+
and12List.add(two);
234+
AndCondition and12 = new AndCondition(and12List);
235+
236+
NotCondition scenario11 = new NotCondition(and12);
237+
238+
// Scenario 12 - ["or", "1", "100000"]
239+
List<Condition> scenario12List = new ArrayList<>();
240+
scenario12List.add(one);
241+
AudienceIdCondition unknownAudience = new AudienceIdCondition("100000");
242+
scenario12List.add(unknownAudience);
243+
244+
OrCondition scenario12 = new OrCondition(scenario12List);
245+
246+
// Scenario 13 - ["and", ["and", invalidAudienceIdCondition]] which becomes// the scenario of ["and", "and"] and results in empty string.
247+
AudienceIdCondition invalidAudience = new AudienceIdCondition("5");
248+
List<Condition> invalidIdList = new ArrayList<>();
249+
invalidIdList.add(invalidAudience);
250+
AndCondition andCondition = new AndCondition(invalidIdList);
251+
List<Condition> andInvalidAudienceId = new ArrayList<>();
252+
andInvalidAudienceId.add(andCondition);
253+
AndCondition scenario13 = new AndCondition(andInvalidAudienceId);
254+
255+
List<Condition> conditionTestScenarios = new ArrayList<>();
256+
conditionTestScenarios.add(scenario1);
257+
conditionTestScenarios.add(scenario2);
258+
conditionTestScenarios.add(scenario3);
259+
conditionTestScenarios.add(scenario4);
260+
conditionTestScenarios.add(scenario5);
261+
conditionTestScenarios.add(scenario6);
262+
conditionTestScenarios.add(scenario7);
263+
conditionTestScenarios.add(scenario8);
264+
conditionTestScenarios.add(scenario9);
265+
conditionTestScenarios.add(scenario10);
266+
conditionTestScenarios.add(scenario11);
267+
conditionTestScenarios.add(scenario12);
268+
conditionTestScenarios.add(scenario13);
269+
270+
return conditionTestScenarios;
271+
}
272+
273+
private Holdout makeMockHoldoutWithStatus(Holdout.HoldoutStatus status, Condition audienceConditions) {
274+
return new Holdout("12345",
275+
"mockHoldoutKey",
276+
status.toString(),
277+
Collections.<String>emptyList(),
278+
audienceConditions,
279+
Collections.<Variation>emptyList(),
280+
Collections.<String, String>emptyMap(),
281+
Collections.<TrafficAllocation>emptyList()
282+
);
283+
}
284+
}

0 commit comments

Comments
 (0)