/*************************GO-LICENSE-START*********************************
* Copyright 2014 ThoughtWorks, Inc.
*
* 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.
*************************GO-LICENSE-END***********************************/
package com.thoughtworks.go.server.service.support.toggle;
import com.thoughtworks.go.server.cache.GoCache;
import com.thoughtworks.go.server.domain.support.toggle.FeatureToggle;
import com.thoughtworks.go.server.domain.support.toggle.FeatureToggles;
import com.thoughtworks.go.server.service.StubGoCache;
import com.thoughtworks.go.server.transaction.TestTransactionSynchronizationManager;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
public class FeatureToggleServiceTest {
@Mock
private FeatureToggleRepository repository;
@Mock
private GoCache goCache;
@Before
public void setUp() throws Exception {
initMocks(this);
}
@Test
public void shouldListAllFeatureToggles() throws Exception {
FeatureToggles existingToggles = new FeatureToggles(
new FeatureToggle("key1", "description1", true),
new FeatureToggle("key2", "description2", false)
);
when(repository.availableToggles()).thenReturn(existingToggles);
when(repository.userToggles()).thenReturn(new FeatureToggles());
FeatureToggleService service = new FeatureToggleService(repository, goCache);
assertThat(service.allToggles(), is(existingToggles));
}
@Test
public void shouldKnowWhetherAToggleIsOnOrOff() throws Exception {
FeatureToggles existingToggles = new FeatureToggles(
new FeatureToggle("key1", "description1", true),
new FeatureToggle("key2", "description2", false)
);
when(repository.availableToggles()).thenReturn(existingToggles);
when(repository.userToggles()).thenReturn(new FeatureToggles());
FeatureToggleService service = new FeatureToggleService(repository, goCache);
assertThat(service.isToggleOn("key1"), is(true));
assertThat(service.isToggleOn("key2"), is(false));
}
@Test
public void shouldSayThatNonExistentTogglesAreOff() throws Exception {
FeatureToggles existingToggles = new FeatureToggles(
new FeatureToggle("key1", "description1", true),
new FeatureToggle("key2", "description2", false)
);
when(repository.availableToggles()).thenReturn(existingToggles);
when(repository.userToggles()).thenReturn(new FeatureToggles());
FeatureToggleService service = new FeatureToggleService(repository, goCache);
assertThat(service.isToggleOn("NON_EXISTENT_KEY"), is(false));
}
@Test
public void shouldOverrideAvailableToggleValuesWithValuesFromUsersToggles() throws Exception {
FeatureToggle availableToggle1 = new FeatureToggle("key1", "desc1", true);
FeatureToggle availableToggle2 = new FeatureToggle("key2", "desc2", true);
FeatureToggle availableToggle3 = new FeatureToggle("key3", "desc3", true);
when(repository.availableToggles()).thenReturn(new FeatureToggles(availableToggle1, availableToggle2, availableToggle3));
FeatureToggle userToggle1 = new FeatureToggle("key1", "NEW_desc1_WITH_NO_change_to_value", true);
FeatureToggle userToggle2 = new FeatureToggle("key2", "NEW_desc2_WITH_CHANGE_TO_VALUE", false);
when(repository.userToggles()).thenReturn(new FeatureToggles(userToggle1, userToggle2));
FeatureToggleService service = new FeatureToggleService(repository, goCache);
FeatureToggles toggles = service.allToggles();
assertThat(toggles.all().size(), is(3));
assertThat(toggles.all().get(0), is(new FeatureToggle("key1", "NEW_desc1_WITH_NO_change_to_value", true).withValueHasBeenChangedFlag(false)));
assertThat(toggles.all().get(1), is(new FeatureToggle("key2", "NEW_desc2_WITH_CHANGE_TO_VALUE", false).withValueHasBeenChangedFlag(true)));
assertThat(toggles.all().get(2), is(new FeatureToggle("key3", "desc3", true).withValueHasBeenChangedFlag(false)));
}
@Test
public void shouldAllowChangingValueOfAValidFeatureToggle() throws Exception {
FeatureToggle availableToggle1 = new FeatureToggle("key1", "desc1", true);
when(repository.availableToggles()).thenReturn(new FeatureToggles(availableToggle1));
when(repository.userToggles()).thenReturn(new FeatureToggles());
FeatureToggleService service = new FeatureToggleService(repository, goCache);
service.changeValueOfToggle("key1", false);
verify(repository).changeValueOfToggle("key1", false);
}
@Test
public void shouldNotAllowChangingValueOfAnInvalidFeatureToggle() throws Exception {
FeatureToggle availableToggle1 = new FeatureToggle("key1", "desc1", true);
when(repository.availableToggles()).thenReturn(new FeatureToggles(availableToggle1));
when(repository.userToggles()).thenReturn(new FeatureToggles());
FeatureToggleService service = new FeatureToggleService(repository, goCache);
try {
service.changeValueOfToggle("keyNOTVALID", true);
fail("This should have failed with an exception, since the feature toggle is invalid.");
} catch (RuntimeException e) {
assertThat(e.getMessage(), is("Feature toggle: 'keyNOTVALID' is not valid."));
}
}
@Test
public void shouldCacheFeatureToggleStatus() throws Exception {
when(repository.availableToggles()).thenReturn(new FeatureToggles(new FeatureToggle("key1", "desc1", true)));
when(repository.userToggles()).thenReturn(new FeatureToggles());
FeatureToggleService service = new FeatureToggleService(repository, new StubGoCache(new TestTransactionSynchronizationManager()));
service.allToggles();
service.allToggles();
service.isToggleOn("key1");
service.isToggleOn("someOtherKey");
verify(repository, times(1)).availableToggles();
}
@Test
public void shouldInvalidateCacheWhenAFeatureTogglesValueIsChanged() throws Exception {
when(repository.availableToggles()).thenReturn(new FeatureToggles(new FeatureToggle("key1", "desc1", true)));
when(repository.userToggles()).thenReturn(new FeatureToggles());
FeatureToggleService service = new FeatureToggleService(repository, new StubGoCache(new TestTransactionSynchronizationManager()));
service.allToggles();
verify(repository, times(1)).availableToggles();
service.changeValueOfToggle("key1", false);
verify(repository, times(1)).availableToggles();
service.allToggles();
verify(repository, times(2)).availableToggles();
}
}