mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	unleash-client-java 'cloned' into it's own repo
This commit is contained in:
		
							parent
							
								
									66f96affeb
								
							
						
					
					
						commit
						642a8e4fa0
					
				| @ -1,13 +0,0 @@ | ||||
| # The Unleash Client 4 Java | ||||
| 
 | ||||
| ## Awesome API | ||||
| 
 | ||||
| It is really simple to use unleash. | ||||
| 
 | ||||
| ```java | ||||
| if(unleash.isEnabled("AwesomeFeature")) { | ||||
|   //do some magic | ||||
| } else { | ||||
|   //do old boring stuff | ||||
| } | ||||
| ``` | ||||
| @ -1,76 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
| 
 | ||||
|     <parent> | ||||
|         <groupId>org.sonatype.oss</groupId> | ||||
|         <artifactId>oss-parent</artifactId> | ||||
|         <version>7</version> | ||||
|     </parent> | ||||
| 
 | ||||
|     <groupId>no.finn.unleash</groupId> | ||||
|     <artifactId>unleash-client-java</artifactId> | ||||
|     <version>1.0-SNAPSHOT</version> | ||||
| 
 | ||||
|     <properties> | ||||
|         <version.log4j2>2.0-rc1</version.log4j2> | ||||
|     </properties> | ||||
| 
 | ||||
|     <dependencies> | ||||
| 
 | ||||
|         <!-- | ||||
|           TODO: we should write our own manual json serialize/deserializer | ||||
|           to avvoid this dependency | ||||
|         --> | ||||
|         <dependency> | ||||
|             <groupId>com.google.code.gson</groupId> | ||||
|             <artifactId>gson</artifactId> | ||||
|             <version>2.2.4</version> | ||||
|         </dependency> | ||||
| 
 | ||||
|         <dependency> | ||||
|             <groupId>org.apache.logging.log4j</groupId> | ||||
|             <artifactId>log4j-api</artifactId> | ||||
|             <version>${version.log4j2}</version> | ||||
|         </dependency> | ||||
| 
 | ||||
|         <!-- Test dependencies --> | ||||
|         <dependency> | ||||
|             <groupId>junit</groupId> | ||||
|             <artifactId>junit</artifactId> | ||||
|             <version>4.11</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
| 
 | ||||
|         <dependency> | ||||
|             <groupId>org.mockito</groupId> | ||||
|             <artifactId>mockito-all</artifactId> | ||||
|             <version>1.9.5</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
| 
 | ||||
|         <dependency> | ||||
|             <groupId>org.apache.logging.log4j</groupId> | ||||
|             <artifactId>log4j-core</artifactId> | ||||
|             <version>${version.log4j2}</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
| 
 | ||||
|     </dependencies> | ||||
| 
 | ||||
|     <build> | ||||
|         <plugins> | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-compiler-plugin</artifactId> | ||||
|                 <version>3.1</version> | ||||
|                 <configuration> | ||||
|                     <source>1.8</source> | ||||
|                     <target>1.8</target> | ||||
|                 </configuration> | ||||
|             </plugin> | ||||
|         </plugins> | ||||
|     </build> | ||||
| </project> | ||||
| @ -1,35 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| 
 | ||||
| import java.io.*; | ||||
| import java.util.Collections; | ||||
| 
 | ||||
| class BackupFileHandler { | ||||
|     private static final Logger LOG = LogManager.getLogger(); | ||||
|     private static final String BACKUP_FILE = | ||||
|             System.getProperty("java.io.tmpdir") + File.separatorChar + "unleash-repo.json"; | ||||
| 
 | ||||
| 
 | ||||
|     ToggleCollection read() { | ||||
|         LOG.info("Unleash will try to load feature toggle states from temporary backup"); | ||||
|         try (FileReader reader = new FileReader(BACKUP_FILE)) { | ||||
|             BufferedReader br = new BufferedReader(reader); | ||||
|             return JsonToggleParser.fromJson(br); | ||||
|         } catch (FileNotFoundException e) { | ||||
|             LOG.warn("Unable to locate backup file:'{}'", BACKUP_FILE, e); | ||||
|         } catch (IOException e) { | ||||
|             LOG.error("Failed to read backup file:'{}'", BACKUP_FILE, e); | ||||
|         } | ||||
|         return new ToggleCollection(Collections.emptyList()); | ||||
|     } | ||||
| 
 | ||||
|     void write(ToggleCollection toggleCollection) { | ||||
|         try (FileWriter writer = new FileWriter(BACKUP_FILE)) { | ||||
|             writer.write(JsonToggleParser.toJsonString(toggleCollection)); | ||||
|         } catch (IOException e) { | ||||
|             LOG.warn("Unleash was unable to backup feature toggles to file: {}", BACKUP_FILE, e); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| final class DefaultStrategy implements Strategy { | ||||
|     public static final String NAME = "default"; | ||||
| 
 | ||||
|     @Override | ||||
|     public String getName() { | ||||
|         return NAME; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isEnabled(Map<String, String> parameters) { | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| @ -1,67 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| import java.util.concurrent.*; | ||||
| 
 | ||||
| public final class FeatureToggleRepository implements ToggleRepository { | ||||
|     private static final Logger LOG = LogManager.getLogger(); | ||||
| 
 | ||||
|     private static final ScheduledThreadPoolExecutor TIMER = new ScheduledThreadPoolExecutor( | ||||
|             1, | ||||
|             new ThreadFactory() { | ||||
|                 @Override | ||||
|                 public Thread newThread(final Runnable r) { | ||||
|                     Thread thread = Executors.defaultThreadFactory().newThread(r); | ||||
|                     thread.setName("unleash-toggle-repository"); | ||||
|                     thread.setDaemon(true); | ||||
|                     return thread; | ||||
|                 } | ||||
|             }); | ||||
| 
 | ||||
|     static { | ||||
|         TIMER.setRemoveOnCancelPolicy(true); | ||||
|     } | ||||
| 
 | ||||
|     private final BackupFileHandler featureToggleBackupFileHandler; | ||||
|     private final ToggleFetcher toggleFetcher; | ||||
| 
 | ||||
|     private ToggleCollection toggleCollection; | ||||
| 
 | ||||
|     public FeatureToggleRepository(URI featuresUri, long pollIntervalSeconds) { | ||||
|         featureToggleBackupFileHandler = new BackupFileHandler(); | ||||
|         toggleFetcher = new HttpToggleFetcher(featuresUri); | ||||
| 
 | ||||
|         toggleCollection = featureToggleBackupFileHandler.read(); | ||||
|         startBackgroundPolling(pollIntervalSeconds); | ||||
|     } | ||||
| 
 | ||||
|     private ScheduledFuture startBackgroundPolling(long pollIntervalSeconds) { | ||||
|         try { | ||||
|             return TIMER.scheduleAtFixedRate(new Runnable() { | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     try { | ||||
|                         Response response = toggleFetcher.fetchToggles(); | ||||
|                         if (response.getStatus() == Response.Status.CHANGED) { | ||||
|                             featureToggleBackupFileHandler.write(toggleCollection); | ||||
|                             toggleCollection = response.getToggleCollection(); | ||||
|                         } | ||||
|                     } catch (UnleashException e) { | ||||
|                         LOG.warn("Could not refresh feature toggles", e); | ||||
|                     } | ||||
|                 } | ||||
|             }, pollIntervalSeconds, pollIntervalSeconds, TimeUnit.SECONDS); | ||||
|         } catch (RejectedExecutionException ex) { | ||||
|             LOG.error("Unleash background task crashed", ex); | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Toggle getToggle(String name) { | ||||
|         return toggleCollection.getToggle(name); | ||||
|     } | ||||
| } | ||||
| @ -1,62 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.net.HttpURLConnection; | ||||
| import java.net.MalformedURLException; | ||||
| import java.net.URI; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| 
 | ||||
| final class HttpToggleFetcher implements ToggleFetcher { | ||||
|     public static final int CONNECT_TIMEOUT = 10000; | ||||
|     private String etag = null; | ||||
| 
 | ||||
|     private final URL toggleUrl; | ||||
| 
 | ||||
|     public HttpToggleFetcher(URI repo) { | ||||
|         try { | ||||
|             toggleUrl = repo.toURL(); | ||||
|         } catch (MalformedURLException ex) { | ||||
|             throw new UnleashException("Invalid repo uri", ex); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Response fetchToggles() throws UnleashException { | ||||
|         HttpURLConnection connection = null; | ||||
|         try { | ||||
|             connection = (HttpURLConnection) toggleUrl.openConnection(); | ||||
|             connection.setConnectTimeout(CONNECT_TIMEOUT); | ||||
|             connection.setReadTimeout(CONNECT_TIMEOUT); | ||||
|             connection.setRequestProperty("If-None-Match", etag); | ||||
|             connection.connect(); | ||||
| 
 | ||||
|             int responseCode = connection.getResponseCode(); | ||||
|             if(responseCode < 300) { | ||||
|                 return getToggleResponse(connection); | ||||
|             } else { | ||||
|                 return new Response(Response.Status.NOT_CHANGED); | ||||
|             } | ||||
|         } catch (IOException e) { | ||||
|             throw new UnleashException("Could not fetch toggles", e); | ||||
|         } finally { | ||||
|             if(connection != null) { | ||||
|                 connection.disconnect(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private Response getToggleResponse(HttpURLConnection request) throws IOException { | ||||
|         etag = request.getHeaderField("ETag"); | ||||
| 
 | ||||
|         try(BufferedReader reader = new BufferedReader( | ||||
|                 new InputStreamReader((InputStream) request.getContent(), StandardCharsets.UTF_8))) { | ||||
| 
 | ||||
|             ToggleCollection toggles = JsonToggleParser.fromJson(reader); | ||||
|             return new Response(Response.Status.CHANGED, toggles); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,29 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| 
 | ||||
| import java.io.Reader; | ||||
| import java.util.Collection; | ||||
| 
 | ||||
| final class JsonToggleParser { | ||||
| 
 | ||||
|     private JsonToggleParser() { | ||||
|     } | ||||
| 
 | ||||
|     public static String toJsonString(ToggleCollection toggleCollection) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         return gson.toJson(toggleCollection); | ||||
|     } | ||||
| 
 | ||||
|     public static Collection<Toggle> fromJson(String jsonString) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         return gson.fromJson(jsonString, ToggleCollection.class).getFeatures(); | ||||
|     } | ||||
| 
 | ||||
|     public static ToggleCollection fromJson(Reader reader) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         ToggleCollection gsonCollection = gson.fromJson(reader, ToggleCollection.class); | ||||
|         return new ToggleCollection(gsonCollection.getFeatures()); | ||||
|     } | ||||
| } | ||||
| @ -1,28 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| 
 | ||||
| final class Response { | ||||
|     enum Status {NOT_CHANGED, CHANGED} | ||||
| 
 | ||||
|     private final Status status; | ||||
|     private final ToggleCollection toggleCollection; | ||||
| 
 | ||||
|     public Response(Status status, ToggleCollection toggleCollection) { | ||||
|         this.status = status; | ||||
|         this.toggleCollection = toggleCollection; | ||||
|     } | ||||
| 
 | ||||
|     public Response(Status status) { | ||||
|         this.status = status; | ||||
|         this.toggleCollection = new ToggleCollection(Collections.emptyList()); | ||||
|     } | ||||
| 
 | ||||
|     public Status getStatus() { | ||||
|         return status; | ||||
|     } | ||||
| 
 | ||||
|     public ToggleCollection getToggleCollection() { | ||||
|         return toggleCollection; | ||||
|     } | ||||
| } | ||||
| @ -1,9 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public interface Strategy { | ||||
|     String getName(); | ||||
| 
 | ||||
|     boolean isEnabled(Map<String, String> parameters); | ||||
| } | ||||
| @ -1,43 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public final class Toggle { | ||||
|     private final String name; | ||||
|     private final boolean enabled; | ||||
|     private final String strategy; | ||||
|     private final Map<String, String> parameters; | ||||
| 
 | ||||
|     public Toggle(String name, boolean enabled, String strategy, Map<String, String> parameters) { | ||||
|         this.name = name; | ||||
|         this.enabled = enabled; | ||||
|         this.strategy = strategy; | ||||
|         this.parameters = parameters; | ||||
|     } | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isEnabled() { | ||||
|         return enabled; | ||||
|     } | ||||
| 
 | ||||
|     public String getStrategy() { | ||||
|         return strategy; | ||||
|     } | ||||
| 
 | ||||
|     public Map<String, String> getParameters() { | ||||
|         return parameters; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "Toggle{" + | ||||
|                 "name='" + name + '\'' + | ||||
|                 ", enabled=" + enabled + | ||||
|                 ", strategy='" + strategy + '\'' + | ||||
|                 ", parameters=" + parameters + | ||||
|                 '}'; | ||||
|     } | ||||
| } | ||||
| @ -1,25 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| final class ToggleCollection { | ||||
|     private Collection<Toggle> features = Collections.emptyList(); | ||||
|     private Map<String, Toggle> cache; | ||||
| 
 | ||||
|     ToggleCollection(final Collection<Toggle> features) { | ||||
|         this.features = features; | ||||
|         cache = new HashMap<>(); | ||||
|         features.forEach(toggle -> cache.put(toggle.getName(), toggle)); | ||||
|     } | ||||
| 
 | ||||
|     Collection<Toggle> getFeatures() { | ||||
|         return features; | ||||
|     } | ||||
| 
 | ||||
|     Toggle getToggle(final String name) { | ||||
|         return cache.get(name); | ||||
|     } | ||||
| } | ||||
| @ -1,5 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| public interface ToggleFetcher { | ||||
|    Response fetchToggles() throws UnleashException; | ||||
| } | ||||
| @ -1,5 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| public interface ToggleRepository { | ||||
|     Toggle getToggle(String name); | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| final class UnknownStrategy implements Strategy { | ||||
|     public static final String NAME = "unknown"; | ||||
| 
 | ||||
|     @Override | ||||
|     public String getName() { | ||||
|         return NAME; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isEnabled(Map<String, String> parameters) { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| @ -1,55 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public final class Unleash { | ||||
|     private static final DefaultStrategy DEFAULT_STRATEGY = new DefaultStrategy(); | ||||
|     private static final UnknownStrategy UNKNOWN_STRATEGY = new UnknownStrategy(); | ||||
| 
 | ||||
|     private final ToggleRepository toggleRepository; | ||||
|     private final Map<String, Strategy> strategyMap; | ||||
| 
 | ||||
|     public Unleash(ToggleRepository toggleRepository, Strategy... strategies) { | ||||
|         this.toggleRepository = toggleRepository; | ||||
|         this.strategyMap = buildStrategyMap(strategies); | ||||
|     } | ||||
| 
 | ||||
|     public boolean isEnabled(final String toggleName) { | ||||
|         return isEnabled(toggleName, false); | ||||
|     } | ||||
| 
 | ||||
|     public boolean isEnabled(final String toggleName, final boolean defaultSetting) { | ||||
|         Toggle toggle = toggleRepository.getToggle(toggleName); | ||||
| 
 | ||||
|         if (toggle == null) { | ||||
|             return defaultSetting; | ||||
|         } | ||||
| 
 | ||||
|         Strategy strategy = getStrategy(toggle.getStrategy()); | ||||
|         return toggle.isEnabled() && strategy.isEnabled(toggle.getParameters()); | ||||
|     } | ||||
| 
 | ||||
|     private Map<String, Strategy> buildStrategyMap(Strategy[] strategies) { | ||||
|         Map<String, Strategy> map = new HashMap<>(); | ||||
| 
 | ||||
|         map.put(DEFAULT_STRATEGY.getName(), DEFAULT_STRATEGY); | ||||
| 
 | ||||
|         if (strategies != null) { | ||||
|             for (Strategy strategy : strategies) { | ||||
|                 map.put(strategy.getName(), strategy); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return map; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private Strategy getStrategy(String strategy) { | ||||
|         if (strategyMap.containsKey(strategy)) { | ||||
|             return strategyMap.get(strategy); | ||||
|         } else { | ||||
|             return UNKNOWN_STRATEGY; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,8 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| public class UnleashException extends RuntimeException { | ||||
| 
 | ||||
|     public UnleashException(String message, Throwable cause) { | ||||
|         super(message, cause); | ||||
|     } | ||||
| } | ||||
| @ -1,36 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static org.hamcrest.CoreMatchers.is; | ||||
| import static org.junit.Assert.assertThat; | ||||
| 
 | ||||
| public class JsonToggleParserTest { | ||||
| 
 | ||||
|     @Test | ||||
|     public void should_deserialize_correctly() throws IOException { | ||||
|         String content = readFile("/features.json"); | ||||
|         List<Toggle> toggles = new ArrayList<>(JsonToggleParser.fromJson(content)); | ||||
| 
 | ||||
|         assertThat(toggles.size(), is(3)); | ||||
|     } | ||||
| 
 | ||||
|     private String readFile(String filename) throws IOException { | ||||
|         InputStream in = this.getClass().getResourceAsStream(filename); | ||||
|         InputStreamReader reader = new InputStreamReader(in); | ||||
|         BufferedReader br = new BufferedReader(reader); | ||||
|         StringBuilder builder = new StringBuilder(); | ||||
|         String line; | ||||
|         while((line = br.readLine()) != null) { | ||||
|             builder.append(line); | ||||
|         } | ||||
|         return builder.toString(); | ||||
|     } | ||||
| } | ||||
| @ -1,49 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| import java.util.Random; | ||||
| 
 | ||||
| public class ManualTesting { | ||||
|     public static void main(String[] args) throws Exception { | ||||
|         ToggleRepository repository = new FeatureToggleRepository(URI.create("http://localhost:4242/features"), 1); | ||||
| 
 | ||||
| 
 | ||||
|         Unleash unleash = new Unleash(repository); | ||||
| 
 | ||||
|         for(int i=0;i<100;i++) { | ||||
|             (new Thread(new UnleashThread(unleash, "thread-"+i, 100))).start(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     static class UnleashThread implements Runnable { | ||||
| 
 | ||||
|         final Unleash unleash; | ||||
|         final String name; | ||||
|         final int maxRounds; | ||||
|         int currentRound = 0; | ||||
| 
 | ||||
|         UnleashThread(Unleash unleash, String name, int maxRounds) { | ||||
|             this.unleash = unleash; | ||||
|             this.name = name; | ||||
|             this.maxRounds = maxRounds; | ||||
|         } | ||||
| 
 | ||||
|         public void run() { | ||||
|             while(currentRound < maxRounds) { | ||||
|                 currentRound++; | ||||
|                 long startTime = System.nanoTime(); | ||||
|                 boolean enabled = unleash.isEnabled("featureX"); | ||||
|                 long timeUsed = System.nanoTime() - startTime; | ||||
| 
 | ||||
|                 System.out.println(name + "\t" +"featureX" +":"  + enabled + "\t " + timeUsed + "ns"); | ||||
| 
 | ||||
|                 try { | ||||
|                     //Wait 1 to 10ms before next round | ||||
|                     Thread.sleep(new Random().nextInt(10000)); | ||||
|                 } catch (InterruptedException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,56 +0,0 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import static org.hamcrest.CoreMatchers.is; | ||||
| import static org.junit.Assert.assertThat; | ||||
| import static org.mockito.Mockito.*; | ||||
| 
 | ||||
| public class UnleashTest { | ||||
| 
 | ||||
|     private ToggleRepository toggleRepository; | ||||
|     private Unleash unleash; | ||||
| 
 | ||||
|     @Before | ||||
|     public void setup() { | ||||
|         toggleRepository = mock(ToggleRepository.class); | ||||
|         unleash = new Unleash(toggleRepository); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void known_toogle_and_strategy_should_be_active() { | ||||
|         when(toggleRepository.getToggle("test")).thenReturn(new Toggle("test", true, "default", null)); | ||||
| 
 | ||||
|         assertThat(unleash.isEnabled("test"), is(true)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void unknown_strategy_should_be_considered_inactive() { | ||||
|         when(toggleRepository.getToggle("test")).thenReturn(new Toggle("test", true, "whoot_strat", null)); | ||||
| 
 | ||||
|         assertThat(unleash.isEnabled("test"), is(false)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void unknown_feature_should_be_considered_inactive() { | ||||
|         when(toggleRepository.getToggle("test")).thenReturn(null); | ||||
| 
 | ||||
|         assertThat(unleash.isEnabled("test"), is(false)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void should_register_custom_strategies() { | ||||
|         //custom strategy | ||||
|         Strategy customStrategy = mock(Strategy.class); | ||||
|         when(customStrategy.getName()).thenReturn("custom"); | ||||
| 
 | ||||
|         //register custom strategy | ||||
|         unleash = new Unleash(toggleRepository, customStrategy); | ||||
|         when(toggleRepository.getToggle("test")).thenReturn(new Toggle("test", true, "custom", null)); | ||||
| 
 | ||||
|         unleash.isEnabled("test"); | ||||
| 
 | ||||
|         verify(customStrategy, times(1)).isEnabled(anyMap()); | ||||
|     } | ||||
| } | ||||
| @ -1,17 +0,0 @@ | ||||
| package no.finn.unleash.example; | ||||
| 
 | ||||
| import no.finn.unleash.Strategy; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| final class CustomStrategy implements Strategy { | ||||
|     @Override | ||||
|     public String getName() { | ||||
|         return "custom"; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isEnabled(Map<String, String> parameters) { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| @ -1,22 +0,0 @@ | ||||
| package no.finn.unleash.example; | ||||
| 
 | ||||
| import no.finn.unleash.FeatureToggleRepository; | ||||
| import no.finn.unleash.ToggleRepository; | ||||
| import no.finn.unleash.Unleash; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| 
 | ||||
| import static org.junit.Assert.assertFalse; | ||||
| 
 | ||||
| public class UnleashUsageTest { | ||||
| 
 | ||||
|     @Test | ||||
|     public void wire() { | ||||
|         ToggleRepository repository = new FeatureToggleRepository(URI.create("http://localhost:4242/features"), 1); | ||||
| 
 | ||||
|         Unleash unleash = new Unleash(repository, new CustomStrategy()); | ||||
| 
 | ||||
|         assertFalse(unleash.isEnabled("myFeature")); | ||||
|     } | ||||
| } | ||||
| @ -1,23 +0,0 @@ | ||||
| {"features": [ | ||||
|     { | ||||
|         "name": "featureX", | ||||
|         "enabled": true, | ||||
|         "strategy": "default" | ||||
|     }, | ||||
|     { | ||||
|         "name": "featureY", | ||||
|         "enabled": false, | ||||
|         "strategy": "baz", | ||||
|         "parameters": { | ||||
|             "foo": "bar" | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "name": "featureZ", | ||||
|         "enabled": true, | ||||
|         "strategy": "baz", | ||||
|         "parameters": { | ||||
|             "foo": "rab" | ||||
|         } | ||||
|     } | ||||
| ]} | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user