From ea41cdf06c50d07756362af31511e41efaa040e8 Mon Sep 17 00:00:00 2001 From: mans4singh Date: Wed, 28 Sep 2016 12:29:22 -0700 Subject: [PATCH] Corrected empty bucket get assignment bug and removed extra method from interface Assignment --- .../intuit/wasabi/assignment/Assignments.java | 26 ----- .../assignment/impl/AssignmentsImpl.java | 8 +- .../EmptyBucketGetUserAssignmentTest.java | 99 +++++++++++++++++++ ...ketGetUserAssignmentToEmptyBucketTest.java | 85 ++++++++++++++++ .../testng_integrationTests.xml | 2 + 5 files changed, 190 insertions(+), 30 deletions(-) create mode 100644 modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentTest.java create mode 100644 modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentToEmptyBucketTest.java diff --git a/modules/assignment/src/main/java/com/intuit/wasabi/assignment/Assignments.java b/modules/assignment/src/main/java/com/intuit/wasabi/assignment/Assignments.java index d768c92c5..6223a121d 100644 --- a/modules/assignment/src/main/java/com/intuit/wasabi/assignment/Assignments.java +++ b/modules/assignment/src/main/java/com/intuit/wasabi/assignment/Assignments.java @@ -83,32 +83,6 @@ Assignment getAssignment(User.ID userID, Application.Name appLabel, Experiment.Label experimentLabel, Context context, boolean createAssignment, boolean ignoreSamplingPercent, SegmentationProfile segmentationProfile, HttpHeaders headers); - /** - * Return an existing assignment for a user, or potentially create a new - * assignment if the user is assignable to this experiment. Includes a Page.Name to identify the page through which - * the assignment was delivered. - * - * @param userID the {@link com.intuit.wasabi.assignmentobjects.User.ID} of the person we want the assignment for - * @param applicationName the {@link com.intuit.wasabi.experimentobjects.Application.Name} the app we want the assignment for - * @param label the {@link com.intuit.wasabi.experimentobjects.Experiment.Label} the experiment - * @param context the {@link Context} of the assignment call - * @param createAssignment true when a new Assignment should be created - * @param ignoreSamplingPercent true if we want to have an assignment independent of the sampling rate - * @param segmentationProfile the {@link SegmentationProfile} to be used for the assignment - * @param headers the {@link HttpHeaders} that can be used by the segmentation - * @param pageName the {@link com.intuit.wasabi.experimentobjects.Page.Name} the page name for the assignment - * @param experiment the {@link Experiment} we want the assignment for - * @param bucketList list of Buckets of this Experiment - * @param userAssignments the already existing assignments - * @param exclusives the experiments that are excluded from the assignment - * @return a brand new or old {@link Assignment} - */ - Assignment getAssignment(User.ID userID, Application.Name applicationName, Experiment.Label label, Context context, - boolean createAssignment, boolean ignoreSamplingPercent, SegmentationProfile segmentationProfile, - HttpHeaders headers, Page.Name pageName, Experiment experiment, BucketList bucketList, - Table userAssignments, - Map> exclusives); - /** * Insert/update a user assignment for this experiment. * diff --git a/modules/assignment/src/main/java/com/intuit/wasabi/assignment/impl/AssignmentsImpl.java b/modules/assignment/src/main/java/com/intuit/wasabi/assignment/impl/AssignmentsImpl.java index fd4c6081e..0d82ff4d9 100644 --- a/modules/assignment/src/main/java/com/intuit/wasabi/assignment/impl/AssignmentsImpl.java +++ b/modules/assignment/src/main/java/com/intuit/wasabi/assignment/impl/AssignmentsImpl.java @@ -220,7 +220,7 @@ public Assignment getSingleAssignment(User.ID userID, Application.Name applicati } Assignment assignment = assignmentsRepository.getAssignment(experimentID, userID, context); - if (assignment == null) { + if (assignment == null || assignment.isBucketEmpty()) { if (createAssignment) { if (experiment.getState() == Experiment.State.PAUSED) { return nullAssignment(userID, applicationName, experimentID, @@ -321,8 +321,7 @@ private Map> getExclusivesList(Experiment.ID * assignment if the user is assignable to this experiment. Includes a Page.Name to identify the page through which * the assignment was delivered. */ - @Override - public Assignment getAssignment(User.ID userID, Application.Name applicationName, Experiment.Label experimentLabel, + protected Assignment getAssignment(User.ID userID, Application.Name applicationName, Experiment.Label experimentLabel, Context context, boolean createAssignment, boolean ignoreSamplingPercent, SegmentationProfile segmentationProfile, HttpHeaders headers, Page.Name pageName, Experiment experiment, BucketList bucketList, @@ -357,8 +356,9 @@ public Assignment getAssignment(User.ID userID, Application.Name applicationName Assignment.Status.EXPERIMENT_EXPIRED); } + // FIXME - Code duplication with getSingleAssignment Assignment assignment = getAssignment(experimentID, userID, context, userAssignments, bucketList); - if (assignment == null) { + if (assignment == null || assignment.isBucketEmpty()) { if (createAssignment) { if (experiment.getState() == Experiment.State.PAUSED) { return nullAssignment(userID, applicationName, experimentID, Assignment.Status.EXPERIMENT_PAUSED); diff --git a/modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentTest.java b/modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentTest.java new file mode 100644 index 000000000..350e86bf8 --- /dev/null +++ b/modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentTest.java @@ -0,0 +1,99 @@ +package com.intuit.wasabi.tests.service; +/******************************************************************************* + * Copyright 2016 Intuit + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +import static com.intuit.wasabi.tests.library.util.ModelAssert.assertEqualModelItems; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.intuit.wasabi.tests.library.TestBase; +import com.intuit.wasabi.tests.library.util.Constants; +import com.intuit.wasabi.tests.library.util.serialstrategies.DefaultNameExclusionStrategy; +import com.intuit.wasabi.tests.library.util.serialstrategies.DefaultNameInclusionStrategy; +import com.intuit.wasabi.tests.model.Assignment; +import com.intuit.wasabi.tests.model.Bucket; +import com.intuit.wasabi.tests.model.Experiment; +import com.intuit.wasabi.tests.model.User; +import com.intuit.wasabi.tests.model.factory.AssignmentFactory; +import com.intuit.wasabi.tests.model.factory.BucketFactory; +import com.intuit.wasabi.tests.model.factory.ExperimentFactory; +import com.intuit.wasabi.tests.model.factory.UserFactory; + +/** + * A test to check if user can be assigned if the previous assignment bucket is empty + */ +public class EmptyBucketGetUserAssignmentTest extends TestBase { + + private Experiment experiment; + private List buckets = new ArrayList<>(); + private User specialUser = UserFactory.createUser("SpecialForBucketTest"); + private User specialUser2 = UserFactory.createUser("Special2ForBucketTest"); + + /** + * Initializes a default experiment. + */ + public EmptyBucketGetUserAssignmentTest() { + setResponseLogLengthLimit(1000); + + experiment = ExperimentFactory.createExperiment(); + + DefaultNameExclusionStrategy experimentComparisonStrategy = new DefaultNameExclusionStrategy("creationTime", "modificationTime", "ruleJson"); + experiment.setSerializationStrategy(experimentComparisonStrategy); + + } + + @Test(dependsOnGroups = {"ping"}) + public void t_GetUserAssignmentEmptyBucket() { + Experiment exp = postExperiment(experiment); + Assert.assertNotNull(exp.creationTime, "Experiment creation failed (No creationTime)."); + Assert.assertNotNull(exp.modificationTime, "Experiment creation failed (No modificationTime)."); + Assert.assertNotNull(exp.state, "Experiment creation failed (No state)."); + experiment.update(exp); + buckets = BucketFactory.createBuckets(experiment, 3); + postBuckets(buckets); + + experiment.state = Constants.EXPERIMENT_STATE_RUNNING; + Experiment exp2 = putExperiment(experiment); + assertEqualModelItems(exp2, experiment); + experiment.update(exp); + + // special user 2 assigned to bucket 0 + Assignment assignment = AssignmentFactory.createAssignment() + .setAssignment(buckets.get(0).label) + .setExperimentLabel(experiment.label) + .setOverwrite(true); + Assignment putAssignmentFor2 = putAssignment(experiment, assignment, specialUser2); + assertEqualModelItems(putAssignmentFor2, assignment, new DefaultNameInclusionStrategy("assignment")); + + // Empty bucke to which use is assigned + List emptyBucket = new ArrayList<>(); + emptyBucket.add(buckets.get(0)); + emptyBucket = putBucketsState(emptyBucket, Constants.BUCKET_STATE_EMPTY); + + // Get assignment after emptying bucket + Assignment getAssignmentAfterEmpty = getAssignment(experiment, specialUser2); + + Assignment assignmentForSpecialAfterReassignment = getAssignment(experiment, specialUser2); + + assertEqualModelItems(assignmentForSpecialAfterReassignment, getAssignmentAfterEmpty, new DefaultNameInclusionStrategy("assignment")); + } +} diff --git a/modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentToEmptyBucketTest.java b/modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentToEmptyBucketTest.java new file mode 100644 index 000000000..0094c6397 --- /dev/null +++ b/modules/functional-test/src/main/java/com/intuit/wasabi/tests/service/EmptyBucketGetUserAssignmentToEmptyBucketTest.java @@ -0,0 +1,85 @@ +package com.intuit.wasabi.tests.service; + +import static com.intuit.wasabi.tests.library.util.ModelAssert.assertEqualModelItems; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpStatus; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.intuit.wasabi.tests.library.TestBase; +import com.intuit.wasabi.tests.library.util.Constants; +import com.intuit.wasabi.tests.library.util.serialstrategies.DefaultNameExclusionStrategy; +import com.intuit.wasabi.tests.library.util.serialstrategies.DefaultNameInclusionStrategy; +import com.intuit.wasabi.tests.model.Assignment; +import com.intuit.wasabi.tests.model.Bucket; +import com.intuit.wasabi.tests.model.Experiment; +import com.intuit.wasabi.tests.model.User; +import com.intuit.wasabi.tests.model.factory.AssignmentFactory; +import com.intuit.wasabi.tests.model.factory.BucketFactory; +import com.intuit.wasabi.tests.model.factory.ExperimentFactory; +import com.intuit.wasabi.tests.model.factory.UserFactory; + +/** + * A test to check if user can be assigned if the previous assignment bucket is empty + */ +public class EmptyBucketGetUserAssignmentToEmptyBucketTest extends TestBase { + + private Experiment experiment; + private List buckets = new ArrayList<>(); + private User specialUser = UserFactory.createUser("SpecialForBucketTest"); + + /** + * Initializes a default experiment. + */ + public EmptyBucketGetUserAssignmentToEmptyBucketTest() { + setResponseLogLengthLimit(1000); + + experiment = ExperimentFactory.createExperiment(); + + DefaultNameExclusionStrategy experimentComparisonStrategy = new DefaultNameExclusionStrategy("creationTime", "modificationTime", "ruleJson"); + experiment.setSerializationStrategy(experimentComparisonStrategy); + + } + + /** + * Test scenario where user is being reassigned from empty bucket to another empty bucket + */ + @Test(dependsOnGroups = {"ping"}) + public void t_AddUserToExperimentWith2BucektsAndEmptyBucketBothAndReassignToAnotherEmptyBucket() { + Experiment exp = postExperiment(experiment); + Assert.assertNotNull(exp.creationTime, "Experiment creation failed."); + Assert.assertNotNull(exp.modificationTime, "Experiment creation failed (No modificationTime)."); + Assert.assertNotNull(exp.state, "Experiment creation failed (No state)."); + experiment.update(exp); + buckets = BucketFactory.createBuckets(experiment, 2); + postBuckets(buckets); + + experiment.state = Constants.EXPERIMENT_STATE_RUNNING; + Experiment exp2 = putExperiment(experiment); + assertEqualModelItems(exp2, experiment); + experiment.update(exp); + + // Assign special user to bucket 0 + Assignment assignment = AssignmentFactory.createAssignment() + .setAssignment(buckets.get(0).label) + .setExperimentLabel(experiment.label) + .setOverwrite(true); + Assignment putAssignment = putAssignment(experiment, assignment, specialUser); + assertEqualModelItems(putAssignment, assignment, new DefaultNameInclusionStrategy("assignment")); + + // Empty both buckets + List emptyBucket = new ArrayList<>(); + emptyBucket.add(buckets.get(0)); + emptyBucket.add(buckets.get(1)); + emptyBucket = putBucketsState(emptyBucket, Constants.BUCKET_STATE_EMPTY); + + // There should be no bucket available for user + Assignment getAssignmentAfterAllEmptyBuckets = getAssignment(experiment, specialUser); + Assert.assertEquals(getAssignmentAfterAllEmptyBuckets.status, Constants.NO_OPEN_BUCKETS); + } +} diff --git a/modules/functional-test/testng_integrationTests.xml b/modules/functional-test/testng_integrationTests.xml index 1b785d1d4..6e2485601 100644 --- a/modules/functional-test/testng_integrationTests.xml +++ b/modules/functional-test/testng_integrationTests.xml @@ -37,6 +37,8 @@ + +