Skip to content

Commit

Permalink
closes #131
Browse files Browse the repository at this point in the history
  • Loading branch information
danhaywood committed May 11, 2015
1 parent e54ce94 commit bc30328
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 19 deletions.
115 changes: 96 additions & 19 deletions junit/src/main/java/org/togglz/junit/TogglzRule.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.togglz.junit;

import java.util.Set;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.togglz.core.Feature;
import org.togglz.core.context.FeatureContext;
import org.togglz.core.util.NamedFeature;
import org.togglz.core.util.Validate;
import org.togglz.junit.vary.VariationSetBuilder;
import org.togglz.testing.TestFeatureManager;
import org.togglz.testing.TestFeatureManagerProvider;

Expand Down Expand Up @@ -49,6 +52,45 @@ public class TogglzRule implements TestRule {
private Feature[] initiallyActive;

private TestFeatureManager featureManager;
private VariationSetBuilder<Feature> variationSetBuilder;

public static class Builder<F extends Feature> {
private final Class<F> featuresClass;
VariationSetBuilder<F> variationSetBuilder;

public Builder(final Class<F> featuresClass) {
this.featuresClass = featuresClass;
this.variationSetBuilder = VariationSetBuilder.create(featuresClass);
}

public Builder enable(final F f) {
variationSetBuilder.enable(f);
return this;
}

public Builder disable(final F f) {
variationSetBuilder.disable(f);
return this;
}

public Builder vary(final F f) {
variationSetBuilder.vary(f);
return this;
}

public TogglzRule build() {
return new TogglzRule(featuresClass, new Feature[0]).with(variationSetBuilder);
}
}

private TogglzRule with(final VariationSetBuilder variationSetBuilder) {
this.variationSetBuilder = variationSetBuilder;
return this;
}

public static <F extends Feature> Builder<F> builder(final Class<F> featuresClass) {
return new Builder<F>(featuresClass);
}

public static TogglzRule allEnabled(Class<? extends Feature> featureClass) {
return new TogglzRule(featureClass, featureClass.getEnumConstants());
Expand Down Expand Up @@ -79,30 +121,65 @@ public void evaluate() throws Throwable {
throw new IllegalStateException("Found existing TestFeatureManager");
}

// create blank instance and set initial state
featureManager = new TestFeatureManager(featureClass);
for (Feature feature : initiallyActive) {
featureManager.enable(feature);
}
WithFeature withFeature = description.getAnnotation(WithFeature.class);
final boolean hasWithFeatureAnnotation = withFeature != null;
final boolean togglzRuleHasVariations = variationSetBuilder != null;

// register the test instance
TestFeatureManagerProvider.setFeatureManager(featureManager);
FeatureContext.clearCache();

WithFeature withFeature = description.getAnnotation(WithFeature.class);
if (withFeature != null) {
for (String featureName : withFeature.value()) {
if (withFeature.disable()) {
disable(new NamedFeature(featureName));
} else {
enable(new NamedFeature(featureName));
if(togglzRuleHasVariations) {

if(hasWithFeatureAnnotation) {
throw new IllegalStateException(
"Cannot combine @WithFeature with @Rule/vary()");
}

final Set<Set<Feature>> permutation = variationSetBuilder.getVariants();

for (Set<Feature> activeFeatures : permutation) {

// create blank instance and set initial state
TestFeatureManager featureManager = new TestFeatureManager(featureClass);
for (Feature feature : activeFeatures) {
featureManager.enable(feature);
}

// register the test instance
TestFeatureManagerProvider.setFeatureManager(featureManager);
FeatureContext.clearCache();

// run the test
base.evaluate();

}
}

// run the test
base.evaluate();

} else {

// create blank instance and set initial state
featureManager = new TestFeatureManager(featureClass);
for (Feature feature : initiallyActive) {
featureManager.enable(feature);
}

// register the test instance
TestFeatureManagerProvider.setFeatureManager(featureManager);
FeatureContext.clearCache();


if (hasWithFeatureAnnotation) {
for (String featureName : withFeature.value()) {
if (withFeature.disable()) {
disable(new NamedFeature(featureName));
} else {
enable(new NamedFeature(featureName));
}
}


}
// run the test
base.evaluate();

}
}

finally {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.togglz.junit.vary;

import java.util.ArrayList;
import java.util.List;

import org.junit.Rule;
import org.junit.Test;
import org.togglz.junit.TogglzRule;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class TogglzRuleWithVariations_CalledMultipleTimes_Test {

@Rule
public TogglzRule togglzRule = TogglzRule.builder(MyFeatures.class)
.vary(MyFeatures.F2)
.vary(MyFeatures.F3)
.build();

private List<Tuple> tuples = new ArrayList<Tuple>();
private int i;

@Test
public void test() {
tuples.add(new Tuple(MyFeatures.F1.isActive(), MyFeatures.F2.isActive(), MyFeatures.F3.isActive()));

i++;
switch (i) {
case 1:
// can't assert here because the order seems to vary between "environment" (ie mvn vs IDE)
break;
case 2:
// can't assert here because the order seems to vary between "environment" (ie mvn vs IDE)
break;
case 3:
// can't assert here because the order seems to vary between "environment" (ie mvn vs IDE)
break;
case 4:
assertTrue(tuples.contains(new Tuple(false,false,false)));
assertTrue(tuples.contains(new Tuple(false,false,true)));
assertTrue(tuples.contains(new Tuple(false,true,false)));
assertTrue(tuples.contains(new Tuple(false, true, true)));
break;
default:
fail();
}
}


static class Tuple {
boolean f1;
boolean f2;
boolean f3;

public Tuple(final boolean f1, final boolean f2, final boolean f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}

@Override
public boolean equals(final Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;

final Tuple tuple = (Tuple) o;

if (f1 != tuple.f1)
return false;
if (f2 != tuple.f2)
return false;
return f3 == tuple.f3;
}

@Override
public int hashCode() {
int result = (f1 ? 1 : 0);
result = 31 * result + (f2 ? 1 : 0);
result = 31 * result + (f3 ? 1 : 0);
return result;
}

@Override public String toString() {
return "Tuple{" +
"f1=" + f1 +
", f2=" + f2 +
", f3=" + f3 +
'}';
}
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.togglz.junit.vary;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.togglz.junit.TogglzRule;

import static org.junit.Assert.assertTrue;

public class TogglzRuleWithVariations_DisableSadCase_Test {

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Rule
public TogglzRule togglzRule = TogglzRule.builder(MyFeatures.class)
.disable(MyFeatures.F1)
.build();

@Test
public void test() {
expectedException.expect(AssertionError.class);

assertTrue(MyFeatures.F1.isActive());
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.togglz.junit.vary;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.togglz.junit.TogglzRule;

import static org.junit.Assert.assertFalse;

public class TogglzRuleWithVariations_EnableSadCase_Test {

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Rule
public TogglzRule togglzRule = TogglzRule.builder(MyFeatures.class)
.enable(MyFeatures.F1)
.build();

@Test
public void test() {
expectedException.expect(AssertionError.class);

assertFalse(MyFeatures.F1.isActive());
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.togglz.junit.vary;

import java.util.ArrayList;
import java.util.List;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.togglz.junit.TogglzRule;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class TogglzRuleWithVariations_HappyCase_Test {

@Rule
public TogglzRule togglzRule = TogglzRule.builder(MyFeatures.class)
.enable(MyFeatures.F1)
.vary(MyFeatures.F2)
.vary(MyFeatures.F3)
.build();

@Test
public void test() {
assertTrue(MyFeatures.F1.isActive());
assertTrue(MyFeatures.F2.isActive() || !MyFeatures.F2.isActive());
assertTrue(MyFeatures.F3.isActive() || !MyFeatures.F3.isActive());
}

}

0 comments on commit bc30328

Please sign in to comment.