diff --git a/feature-toggle/etc/feature-toggle.png b/feature-toggle/etc/feature-toggle.png
new file mode 100644
index 00000000..5c118e57
Binary files /dev/null and b/feature-toggle/etc/feature-toggle.png differ
diff --git a/feature-toggle/etc/feature-toggle.ucls b/feature-toggle/etc/feature-toggle.ucls
new file mode 100644
index 00000000..538d3f41
--- /dev/null
+++ b/feature-toggle/etc/feature-toggle.ucls
@@ -0,0 +1,111 @@
+
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.featuretoggle; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion; +import com.iluwatar.featuretoggle.user.User; +import com.iluwatar.featuretoggle.user.UserGroup; + +import java.util.Properties; + +/** + * The Feature Toggle pattern allows for complete code executions to be turned on or off with ease. This allows features + * to be controlled by either dynamic methods just as {@link User} information or by {@link Properties}. In the App + * below there are two examples. Firstly the {@link Properties} version of the feature toggle, where the enhanced + * version of the welcome message which is personalised is turned either on or off at instance creation. This method + * is not as dynamic as the {@link User} driven version where the feature of the personalised welcome message is + * dependant on the {@link UserGroup} the {@link User} is in. So if the user is a memeber of the + * {@link UserGroup#isPaid(User)} then they get an ehanced version of the welcome message. + * + * Note that this pattern can easily introduce code complexity, and if not kept in check can result in redundant + * unmaintained code within the codebase. + * + */ +public class App { + + /** + * Block 1 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties} setting the feature + * toggle to enabled. + * + * Block 2 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties} setting the feature + * toggle to disabled. Notice the difference with the printed welcome message the username is not included. + * + * Block 3 shows the {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} being + * set up with two users on who is on the free level, while the other is on the paid level. When the + * {@link Service#getWelcomeMessage(User)} is called with the paid {@link User} note that the welcome message + * contains their username, while the same service call with the free tier user is more generic. No username is + * printed. + * + * @see User + * @see UserGroup + * @see Service + * @see PropertiesFeatureToggleVersion + * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion; + */ + public static void main(String[] args) { + + final Properties properties = new Properties(); + properties.put("enhancedWelcome", true); + Service service = new PropertiesFeatureToggleVersion(properties); + final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); + System.out.println(welcomeMessage); + + // --------------------------------------------- + + final Properties turnedOff = new Properties(); + turnedOff.put("enhancedWelcome", false); + Service turnedOffService = new PropertiesFeatureToggleVersion(turnedOff); + final String welcomeMessageturnedOff = turnedOffService.getWelcomeMessage(new User("Jamie No Code")); + System.out.println(welcomeMessageturnedOff); + + // -------------------------------------------- + + final User paidUser = new User("Jamie Coder"); + final User freeUser = new User("Alan Defect"); + + UserGroup.addUserToPaidGroup(paidUser); + UserGroup.addUserToFreeGroup(freeUser); + + final String welcomeMessagePaidUser = service.getWelcomeMessage(paidUser); + final String welcomeMessageFreeUser = service.getWelcomeMessage(freeUser); + System.out.println(welcomeMessageFreeUser); + System.out.println(welcomeMessagePaidUser); + } +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java new file mode 100644 index 00000000..d2542b2b --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java @@ -0,0 +1,54 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.featuretoggle.pattern; + +import com.iluwatar.featuretoggle.user.User; + +/** + * Simple interfaces to allow the calling of the method to generate the welcome message for a given user. While there is + * a helper method to gather the the status of the feature toggle. In some cases there is no need for the + * {@link Service#isEnhanced()} in {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} + * where the toggle is determined by the actual {@link User}. + * + * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion + * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion + * @see User + */ +public interface Service { + + /** + * Generates a welcome message for the passed user. + * + * @param user the {@link User} to be used if the message is to be personalised. + * @return Generated {@link String} welcome message + */ + String getWelcomeMessage(User user); + + /** + * Returns if the welcome message to be displayed will be the enhanced version. + * + * @return Boolean {@value true} if enhanced. + */ + boolean isEnhanced(); + +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java new file mode 100644 index 00000000..761d7d39 --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java @@ -0,0 +1,100 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.featuretoggle.pattern.propertiesversion; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.user.User; + +import java.util.Properties; + +/** + * This example of the Feature Toogle pattern is less dynamic version than + * {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} where the feature is turned on + * or off at the time of creation of the service. This example uses simple Java {@link Properties} however it could as + * easily be done with an external configuration file loaded by Spring and so on. A good example of when to use this + * version of the feature toggle is when new features are being developed. So you could have a configuration property + * boolean named development or some sort of system environment variable. + * + * @see Service + * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion + * @see User + */ +public class PropertiesFeatureToggleVersion implements Service { + + private boolean isEnhanced; + + /** + * Creates an instance of {@link PropertiesFeatureToggleVersion} using the passed {@link Properties} to determine, + * the status of the feature toggle {@link PropertiesFeatureToggleVersion#isEnhanced()}. There is also some defensive + * code to ensure the {@link Properties} passed are as expected. + * + * @param properties {@link Properties} used to configure the service and toggle features. + * @throws IllegalArgumentException when the passed {@link Properties} is not as expected + * @see Properties + */ + public PropertiesFeatureToggleVersion(final Properties properties) { + if (properties == null) { + throw new IllegalArgumentException("No Properties Provided."); + } else { + try { + isEnhanced = (boolean) properties.get("enhancedWelcome"); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid Enhancement Settings Provided."); + } + } + } + + /** + * Generate a welcome message based on the user being passed and the status of the feature toggle. If the enhanced + * version is enabled, then the message will be personalised with the name of the passed {@link User}. However if + * disabled then a generic version fo the message is returned. + * + * @param user the {@link User} to be displayed in the message if the enhanced version is enabled see + * {@link PropertiesFeatureToggleVersion#isEnhanced()}. If the enhanced version is enabled, then the + * message will be personalised with the name of the passed {@link User}. However if disabled then a + * generic version fo the message is returned. + * @return Resulting welcome message. + * @see User + */ + @Override + public String getWelcomeMessage(final User user) { + + if (isEnhanced()) { + return "Welcome " + user + ". You're using the enhanced welcome message."; + } + + return "Welcome to the application."; + } + + /** + * Method that checks if the welcome message to be returned is the enhanced venison or not. For this service it will + * see the value of the boolean that was set in the constructor + * {@link PropertiesFeatureToggleVersion#PropertiesFeatureToggleVersion(Properties)} + * + * @return Boolean value {@value true} if enhanced. + */ + @Override + public boolean isEnhanced() { + return isEnhanced; + } +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java new file mode 100644 index 00000000..124c9533 --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java @@ -0,0 +1,75 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.featuretoggle.pattern.tieredversion; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.user.User; +import com.iluwatar.featuretoggle.user.UserGroup; + +/** + * This example of the Feature Toogle pattern shows how it could be implemented based on a {@link User}. Therefore + * showing its use within a tiered application where the paying users get access to different content or + * better versions of features. So in this instance a {@link User} is passed in and if they are found to be + * on the {@link UserGroup#isPaid(User)} they are welcomed with a personalised message. While the other is more + * generic. However this pattern is limited to simple examples such as the one below. + * + * @see Service + * @see User + * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion + * @see UserGroup + */ +public class TieredFeatureToggleVersion implements Service { + + /** + * Generates a welcome message from the passed {@link User}. The resulting message depends on the group of the + * {@link User}. So if the {@link User} is in the {@link UserGroup#paidGroup} then the enhanced version of the + * welcome message will be returned where the username is displayed. + * + * @param user the {@link User} to generate the welcome message for, different messages are displayed if the user is + * in the {@link UserGroup#isPaid(User)} or {@link UserGroup#freeGroup} + * @return Resulting welcome message. + * @see User + * @see UserGroup + */ + @Override + public String getWelcomeMessage(User user) { + if (UserGroup.isPaid(user)) { + return "You're amazing " + user + ". Thanks for paying for this awesome software."; + } + + return "I suppose you can use this software."; + } + + /** + * Method that checks if the welcome message to be returned is the enhanced version. For this instance as the logic + * is driven by the user group. This method is a little redundant. However can be used to show that there is an + * enhanced version available. + * + * @return Boolean value {@value true} if enhanced. + */ + @Override + public boolean isEnhanced() { + return true; + } + +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java new file mode 100644 index 00000000..ce7b54b7 --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java @@ -0,0 +1,49 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.featuretoggle.user; + +/** + * Used to demonstrate the purpose of the feature toggle. This class actually has nothing to do with the pattern. + */ +public class User { + + private String name; + + /** + * Default Constructor setting the username. + * + * @param name {@link String} to represent the name of the user. + */ + public User(String name) { + this.name = name; + } + + /** + * {@inheritDoc} + * @return The {@link String} representation of the User, in this case just return the name of the user. + */ + @Override + public String toString() { + return name; + } +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java new file mode 100644 index 00000000..c9d9fd02 --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java @@ -0,0 +1,84 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *
+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.featuretoggle.user;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains the lists of users of different groups paid and free. Used to demonstrate the tiered example of feature
+ * toggle. Allowing certain features to be available to only certain groups of users.
+ *
+ * @see User
+ */
+public class UserGroup {
+
+ private static List
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.featuretoggle.pattern.propertiesversion;
+
+import com.iluwatar.featuretoggle.pattern.Service;
+import com.iluwatar.featuretoggle.user.User;
+import org.junit.Test;
+
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class PropertiesFeatureToggleVersionTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullPropertiesPassed() throws Exception {
+ new PropertiesFeatureToggleVersion(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNonBooleanProperty() throws Exception {
+ final Properties properties = new Properties();
+ properties.setProperty("enhancedWelcome", "Something");
+ new PropertiesFeatureToggleVersion(properties);
+ }
+
+ @Test
+ public void testFeatureTurnedOn() throws Exception {
+ final Properties properties = new Properties();
+ properties.put("enhancedWelcome", true);
+ Service service = new PropertiesFeatureToggleVersion(properties);
+ assertTrue(service.isEnhanced());
+ final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code"));
+ assertEquals("Welcome Jamie No Code. You're using the enhanced welcome message.", welcomeMessage);
+ }
+
+ @Test
+ public void testFeatureTurnedOff() throws Exception {
+ final Properties properties = new Properties();
+ properties.put("enhancedWelcome", false);
+ Service service = new PropertiesFeatureToggleVersion(properties);
+ assertFalse(service.isEnhanced());
+ final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code"));
+ assertEquals("Welcome to the application.", welcomeMessage);
+ }
+}
\ No newline at end of file
diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java
new file mode 100644
index 00000000..dca1d9b8
--- /dev/null
+++ b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java
@@ -0,0 +1,64 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.featuretoggle.pattern.tieredversion;
+
+import com.iluwatar.featuretoggle.pattern.Service;
+import com.iluwatar.featuretoggle.user.User;
+import com.iluwatar.featuretoggle.user.UserGroup;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TieredFeatureToggleVersionTest {
+
+ final User paidUser = new User("Jamie Coder");
+ final User freeUser = new User("Alan Defect");
+ final Service service = new TieredFeatureToggleVersion();
+
+ @Before
+ public void setUp() throws Exception {
+ UserGroup.addUserToPaidGroup(paidUser);
+ UserGroup.addUserToFreeGroup(freeUser);
+ }
+
+ @Test
+ public void testGetWelcomeMessageForPaidUser() throws Exception {
+ final String welcomeMessage = service.getWelcomeMessage(paidUser);
+ final String expected = "You're amazing Jamie Coder. Thanks for paying for this awesome software.";
+ assertEquals(expected, welcomeMessage);
+ }
+
+ @Test
+ public void testGetWelcomeMessageForFreeUser() throws Exception {
+ final String welcomeMessage = service.getWelcomeMessage(freeUser);
+ final String expected = "I suppose you can use this software.";
+ assertEquals(expected, welcomeMessage);
+ }
+
+ @Test
+ public void testIsEnhancedAlwaysTrueAsTiered() throws Exception {
+ assertTrue(service.isEnhanced());
+ }
+}
\ No newline at end of file
diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java
new file mode 100644
index 00000000..6659815d
--- /dev/null
+++ b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java
@@ -0,0 +1,59 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.featuretoggle.user;
+
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class UserGroupTest {
+
+ @Test
+ public void testAddUserToFreeGroup() throws Exception {
+ User user = new User("Free User");
+ UserGroup.addUserToFreeGroup(user);
+ assertFalse(UserGroup.isPaid(user));
+ }
+
+ @Test
+ public void testAddUserToPaidGroup() throws Exception {
+ User user = new User("Paid User");
+ UserGroup.addUserToPaidGroup(user);
+ assertTrue(UserGroup.isPaid(user));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddUserToPaidWhenOnFree() throws Exception {
+ User user = new User("Paid User");
+ UserGroup.addUserToFreeGroup(user);
+ UserGroup.addUserToPaidGroup(user);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddUserToFreeWhenOnPaid() throws Exception {
+ User user = new User("Free User");
+ UserGroup.addUserToPaidGroup(user);
+ UserGroup.addUserToFreeGroup(user);
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 993e6edd..077d3c95 100644
--- a/pom.xml
+++ b/pom.xml
@@ -119,6 +119,7 @@