@Test
  public void testSimple_50_50() {
    testDefinition.setSalt(testName);

    final StandardTestChooser chooser = newChooser();
    exerciseChooser(chooser);

    // uncomment this if you need to recompute these values
    //        for (int i = 0; i < counts.length; i++) System.err.println(i + ": " + counts[i] + " /
    // " + hashes[i]);

    // if this ever fails, it means that something is broken about how tests are split
    // and you should investigate why!

    Assert.assertEquals("bucket0 counts", 4999412, counts[0]);
    Assert.assertEquals("bucket1 counts", 5000587, counts[1]);

    Assert.assertEquals("bucket0 hash", 1863060514, hashes[0]);
    Assert.assertEquals("bucket1 hash", 765061458, hashes[1]);
  }
  @Test
  public void test_50_50_withMagicTestSalt() {
    // Now change the spec version and reevaluate
    testDefinition.setSalt("&" + testName);

    final StandardTestChooser chooser = newChooser();
    exerciseChooser(chooser);

    // uncomment this if you need to recompute these values
    //        for (int i = 0; i < counts.length; i++) System.err.println(i + ": " + counts[i] + " /
    // " + hashes[i]);

    // if this ever fails, it means that something is broken about how tests are split
    // and you should investigate why!

    Assert.assertEquals("bucket0 counts", COUNTS_BUCKET0_SALT_AMP_TESTNAME, counts[0]);
    Assert.assertEquals("bucket1 counts", COUNTS_BUCKET1_SALT_AMP_TESTNAME, counts[1]);

    Assert.assertEquals("bucket0 hash", HASH_BUCKET0_SALT_AMP_TESTNAME, hashes[0]);
    Assert.assertEquals("bucket1 hash", HASH_BUCKET1_SALT_AMP_TESTNAME, hashes[1]);
  }
  @Before
  public void setupMocks() throws Exception {
    expressionFactory = new ExpressionFactoryImpl();
    functionMapper = RuleEvaluator.FUNCTION_MAPPER;
    testName = "testName";
    final List<TestBucket> buckets =
        ImmutableList.of(
            new TestBucket("inactive", -1, "zoot", null),
            new TestBucket("control", 0, "zoot", null),
            new TestBucket("test", 1, "zoot", null));
    testDefinition = new ConsumableTestDefinition();
    testDefinition.setConstants(Collections.<String, Object>emptyMap());
    testDefinition.setTestType(TestType.AUTHENTICATED_USER);
    // most tests just set the salt to be the same as the test name
    testDefinition.setSalt(testName);
    testDefinition.setBuckets(buckets);

    updateAllocations(RANGES_50_50);

    final int effBuckets = buckets.size() - 1;
    counts = new int[effBuckets];
    hashes = new int[effBuckets];
  }
  @Test
  public void test50_50_withMagicTestSalt_and_unrelatedTestName() {
    final String originalTestName = testName;
    testName = "someOtherTestName";
    testDefinition.setSalt("&" + originalTestName);

    final StandardTestChooser chooser = newChooser();
    exerciseChooser(chooser);

    // uncomment this if you need to recompute these values
    //        for (int i = 0; i < counts.length; i++) System.err.println(i + ": " + counts[i] + " /
    // " + hashes[i]);

    // if this ever fails, it means that something is broken about how tests are split
    // and you should investigate why!

    // These values should be the same as in the preceding test
    Assert.assertEquals("bucket0 counts", COUNTS_BUCKET0_SALT_AMP_TESTNAME, counts[0]);
    Assert.assertEquals("bucket1 counts", COUNTS_BUCKET1_SALT_AMP_TESTNAME, counts[1]);

    Assert.assertEquals("bucket0 hash", HASH_BUCKET0_SALT_AMP_TESTNAME, hashes[0]);
    Assert.assertEquals("bucket1 hash", HASH_BUCKET1_SALT_AMP_TESTNAME, hashes[1]);
  }
  @Test
  public void testExceptionsDealtWith() {
    final String testName = "test";

    final ConsumableTestDefinition testDefinition = new ConsumableTestDefinition();
    testDefinition.setConstants(Collections.<String, Object>emptyMap());
    testDefinition.setRule("${lang == 'en'}");

    testDefinition.setTestType(TestType.ANONYMOUS_USER);

    // most tests just set the salt to be the same as the test name
    testDefinition.setSalt(testName);
    testDefinition.setBuckets(Collections.<TestBucket>emptyList());

    final RuleEvaluator ruleEvaluator = EasyMock.createMock(RuleEvaluator.class);
    EasyMock.expect(
            ruleEvaluator.evaluateBooleanRule(
                EasyMock.<String>anyObject(), EasyMock.<Map<String, Object>>anyObject()))
        // throw an unexpected type of runtime exception
        .andThrow(new RuntimeException() {})
        // Must be evaluated, or this was not a valid test
        .once();
    EasyMock.replay(ruleEvaluator);

    final TestRangeSelector selector =
        new TestRangeSelector(ruleEvaluator, testName, testDefinition);

    // Ensure no exceptions thrown.
    final TestBucket bucket =
        new StandardTestChooser(selector)
            .choose("identifier", Collections.<String, Object>emptyMap());

    assertEquals("Expected no bucket to be found ", null, bucket);

    EasyMock.verify(ruleEvaluator);
  }