Skip to content

Commit

Permalink
feat: do not return default settings if requested name does not exist (
Browse files Browse the repository at this point in the history
  • Loading branch information
grigoriev authored Jun 5, 2024
1 parent 18905bb commit defe5f0
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public Collection<SettingName> readNames(@NotNull String scope) {
if (names.isEmpty()) {
// If there are no settings persisted - try to create default one
try {
saveDefaultSettingsInGlobalRepo();
saveDefaultSettingsInGlobalScope();
} catch (Exception e) { // If it's not possible to create the settings in read only transaction, so just ignore it
logger.warn("Cannot create the settings in read only transaction, creation will be skipped: " + e.getMessage(), e);
}
Expand Down Expand Up @@ -116,7 +116,7 @@ public Collection<SettingName> readNames(@NotNull String scope) {
private @NotNull T handleMissingValue(@NotNull SettingId id) {
if (DEFAULT_NAME.equals(id.getIdentifier())) {
try {
return saveDefaultSettingsInGlobalRepo();
return saveDefaultSettingsInGlobalScope();
} catch (Exception e) {
logger.warn("Cannot create the settings in read-only transaction, default values will be used: " + e.getMessage(), e);
return defaultValues();
Expand Down Expand Up @@ -232,7 +232,7 @@ private SettingName buildSettingName(String scope, String id) {
.build();
}

private @NotNull T saveDefaultSettingsInGlobalRepo() {
private @NotNull T saveDefaultSettingsInGlobalScope() {
T defaultModel = defaultValues();
defaultModel.setName(DEFAULT_NAME);
return save(DEFAULT_SCOPE, SettingId.fromId(DEFAULT_NAME), defaultModel);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package ch.sbb.polarion.extension.generic.settings;

import ch.sbb.polarion.extension.generic.exception.ObjectNotFoundException;
import ch.sbb.polarion.extension.generic.settings.named_settings.TestModel;
import ch.sbb.polarion.extension.generic.settings.named_settings.TestSettings;
import ch.sbb.polarion.extension.generic.util.ScopeUtils;
import com.polarion.subterra.base.location.ILocation;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedConstruction;
Expand All @@ -12,15 +14,21 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

import static ch.sbb.polarion.extension.generic.settings.NamedSettings.DEFAULT_NAME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
@SuppressWarnings("unused")
class GenericNamedSettingsTest {

@Test
void testBeforeAndAfterSave() {
try (MockedConstruction<SettingsService> mockSettingsService = Mockito.mockConstruction(SettingsService.class);
Expand All @@ -39,6 +47,73 @@ void testBeforeAndAfterSave() {

verify(settingsSpy).beforeSave(model);
verify(settingsSpy).afterSave(model);

assertThrows(IllegalArgumentException.class, () -> {
settingsSpy.save("project/some_project/", SettingId.fromId(""), model);
});
}
}

@Test
void testRead() {
try (MockedStatic<ScopeUtils> mockScopeUtils = mockStatic(ScopeUtils.class)) {
SettingsService settingsService = mock(SettingsService.class);

ILocation mockProjectLocation = mock(ILocation.class);
ILocation mockProjectSettingsFolderLocation = mock(ILocation.class);
when(mockProjectLocation.append(".polarion/extensions/null/Test")).thenReturn(mockProjectSettingsFolderLocation);
ILocation mockProjectTest1Location = mock(ILocation.class);
ILocation mockProjectTest2Location = mock(ILocation.class);
when(mockProjectLocation.append(".polarion/extensions/null/Test/project_test1.settings")).thenReturn(mockProjectTest1Location);
when(mockProjectLocation.append(".polarion/extensions/null/Test/project_test2.settings")).thenReturn(mockProjectTest2Location);

mockScopeUtils.when(() -> ScopeUtils.getContextLocation("project/some_project/")).thenReturn(mockProjectLocation);
when(settingsService.getLastRevision(mockProjectSettingsFolderLocation)).thenReturn("34");
when(settingsService.getPersistedSettingFileNames(mockProjectSettingsFolderLocation)).thenReturn(List.of("project_test1", "project_test2"));

ILocation mockDefaultLocation = mock(ILocation.class);
ILocation mockDefaultSettingsFolderLocation = mock(ILocation.class);
when(mockDefaultLocation.append(".polarion/extensions/null/Test")).thenReturn(mockDefaultSettingsFolderLocation);
ILocation mockDefaultTest1Location = mock(ILocation.class);
when(mockDefaultLocation.append(".polarion/extensions/null/Test/default_test1.settings")).thenReturn(mockDefaultTest1Location);
ILocation mockDefaultDefaultLocation = mock(ILocation.class);
when(mockDefaultLocation.append(".polarion/extensions/null/Test/Default.settings")).thenReturn(mockDefaultDefaultLocation);

mockScopeUtils.when(() -> ScopeUtils.getContextLocation("")).thenReturn(mockDefaultLocation);
when(settingsService.getLastRevision(mockDefaultSettingsFolderLocation)).thenReturn("42");
when(settingsService.getPersistedSettingFileNames(mockDefaultSettingsFolderLocation)).thenReturn(List.of("default_test1"));

TestSettings testSettings = new TestSettings(settingsService);
when(settingsService.read(eq(mockProjectTest1Location), any())).thenReturn(getModelContent("project_test1"));
when(settingsService.read(eq(mockProjectTest2Location), any())).thenReturn(getModelContent("project_test2"));
when(settingsService.read(eq(mockDefaultTest1Location), any())).thenReturn(getModelContent("default_test1"));

TestModel testModelProjectTest1 = testSettings.read("project/some_project/", SettingId.fromName("project_test1"), null);
assertEquals("project_test1", testModelProjectTest1.getName());

TestModel testModelProjectTest2 = testSettings.read("project/some_project/", SettingId.fromName("project_test2"), null);
assertEquals("project_test2", testModelProjectTest2.getName());

TestModel testModelDefaultTest1 = testSettings.read("project/some_project/", SettingId.fromName("default_test1"), null);
assertEquals("default_test1", testModelDefaultTest1.getName());

TestModel testModelGlobalDefaultTest1 = testSettings.read("", SettingId.fromName("default_test1"), null);
assertEquals("default_test1", testModelGlobalDefaultTest1.getName());

assertThrows(ObjectNotFoundException.class, () -> {
TestModel testModelProjectTest1Rev34 = testSettings.read("project/some_project/", SettingId.fromName("default_test1"), "55");
});

assertThrows(ObjectNotFoundException.class, () -> {
TestModel testModelProjectTest1Rev34 = testSettings.read("project/some_project/", SettingId.fromName("unknown"), null);
});

TestModel testModelDefaultSaved = testSettings.read("project/some_project/", SettingId.fromName(DEFAULT_NAME), null);
assertEquals("Default", testModelDefaultSaved.getName());

doThrow(new RuntimeException("test runtime exception")).when(settingsService).save(eq(mockDefaultDefaultLocation), anyString());
TestModel testModelDefaultNotSaved = testSettings.read("project/some_project/", SettingId.fromName(DEFAULT_NAME), null);
assertEquals("Default", testModelDefaultNotSaved.getName());
}
}

Expand All @@ -51,7 +126,7 @@ void testReadNames() {
ILocation mockProjectLocation = mock(ILocation.class);
ILocation mockProjectFolderLocation = mock(ILocation.class);
when(mockProjectLocation.append(anyString())).thenReturn(mockProjectFolderLocation);
mockScopeUtils.when(() -> ScopeUtils.getContextLocation("Test")).thenReturn(mockProjectLocation);
mockScopeUtils.when(() -> ScopeUtils.getContextLocation("project/some_project/")).thenReturn(mockProjectLocation);
when(settingsService.getPersistedSettingFileNames(mockProjectFolderLocation)).thenReturn(Arrays.asList("test1", "test2"));
when(settingsService.getLastRevision(mockProjectFolderLocation)).thenReturn("34");

Expand All @@ -65,24 +140,24 @@ void testReadNames() {
TestSettings testSettings = new TestSettings(settingsService);
when(settingsService.read(any(), any())).thenReturn(getModelContent("test1"), getModelContent("test2"), getModelContent("default1"), getModelContent("default2"));

Collection<SettingName> names = testSettings.readNames("Test");
Collection<SettingName> names = testSettings.readNames("project/some_project/");
assertEquals(Stream.of("test1", "test2", "default1", "default2").sorted().toList(), names.stream().map(SettingName::getName).sorted().toList());

//folder revisions remain the same = used cached values
lenient().when(settingsService.read(any(), any())).thenReturn(getModelContent("test3"), getModelContent("test4"), getModelContent("default3"), getModelContent("default4"));
names = testSettings.readNames("Test");
names = testSettings.readNames("project/some_project/");
assertEquals(Stream.of("test1", "test2", "default1", "default2").sorted().toList(), names.stream().map(SettingName::getName).sorted().toList());

//default folder revision updated = results partially changed
lenient().when(settingsService.read(any(), any())).thenReturn(getModelContent("default3"), getModelContent("default4"));
when(settingsService.getLastRevision(mockDefaultFolderLocation)).thenReturn("43");
names = testSettings.readNames("Test");
names = testSettings.readNames("project/some_project/");
assertEquals(Stream.of("test1", "test2", "default3", "default4").sorted().toList(), names.stream().map(SettingName::getName).sorted().toList());

//project folder revision updated = results changed again
lenient().when(settingsService.read(any(), any())).thenReturn(getModelContent("test3"), getModelContent("test4"));
when(settingsService.getLastRevision(mockProjectFolderLocation)).thenReturn("35");
names = testSettings.readNames("Test");
names = testSettings.readNames("project/some_project/");
assertEquals(Stream.of("test3", "test4", "default3", "default4").sorted().toList(), names.stream().map(SettingName::getName).sorted().toList());
}
}
Expand All @@ -93,36 +168,110 @@ private String getModelContent(String name) {
return testModel.serialize();
}

private static class TestSettings extends GenericNamedSettings<TestModel> {
public TestSettings() {
super("Test");
}
@Test
void testDelete() {
try (MockedStatic<ScopeUtils> mockScopeUtils = mockStatic(ScopeUtils.class)) {
SettingsService settingsService = mock(SettingsService.class);

public TestSettings(SettingsService settingsService) {
super("Test", settingsService);
}
ILocation mockProjectLocation = mock(ILocation.class);
ILocation mockProjectSettingsFolderLocation = mock(ILocation.class);
when(mockProjectLocation.append(".polarion/extensions/null/Test")).thenReturn(mockProjectSettingsFolderLocation);
ILocation mockProjectTest1Location = mock(ILocation.class);
ILocation mockProjectTest2Location = mock(ILocation.class);
when(mockProjectLocation.append(".polarion/extensions/null/Test/project_delete1.settings")).thenReturn(mockProjectTest1Location);

@Override
public @NotNull TestModel defaultValues() {
return new TestModel();
}
mockScopeUtils.when(() -> ScopeUtils.getContextLocation("project/delete_project/")).thenReturn(mockProjectLocation);
when(settingsService.getLastRevision(mockProjectSettingsFolderLocation)).thenReturn("11");
when(settingsService.getPersistedSettingFileNames(mockProjectSettingsFolderLocation)).thenReturn(List.of("project_delete1"));

ILocation mockDefaultLocation = mock(ILocation.class);
ILocation mockDefaultSettingsFolderLocation = mock(ILocation.class);
when(mockDefaultLocation.append(".polarion/extensions/null/Test")).thenReturn(mockDefaultSettingsFolderLocation);
ILocation mockDefaultTest1Location = mock(ILocation.class);
when(mockDefaultLocation.append(".polarion/extensions/null/Test/default_delete1.settings")).thenReturn(mockDefaultTest1Location);

mockScopeUtils.when(() -> ScopeUtils.getContextLocation("")).thenReturn(mockDefaultLocation);
when(settingsService.getLastRevision(mockDefaultSettingsFolderLocation)).thenReturn("66");
when(settingsService.getPersistedSettingFileNames(mockDefaultSettingsFolderLocation)).thenReturn(List.of("default_delete1"));

@Override
public @NotNull String currentBundleTimestamp() {
return "Something";
TestSettings testSettings = new TestSettings(settingsService);
when(settingsService.read(eq(mockProjectTest1Location), any())).thenReturn(getModelContent("project_delete1"));
when(settingsService.read(eq(mockDefaultTest1Location), any())).thenReturn(getModelContent("default_delete1"));

assertThrows(ObjectNotFoundException.class, () -> {
testSettings.delete("project/delete_project/", SettingId.fromName("unknown"));
});

testSettings.delete("project/delete_project/", SettingId.fromName("project_delete1"));
verify(settingsService).delete(mockProjectTest1Location);

assertThrows(ObjectNotFoundException.class, () -> {
testSettings.delete("project/delete_project/", SettingId.fromName("default_delete1"));
});
}
}

public static class TestModel extends SettingsModel {
@Test
void testListRevisions() {
try (MockedStatic<ScopeUtils> mockScopeUtils = mockStatic(ScopeUtils.class)) {
mockScopeUtils.when(() -> ScopeUtils.getProjectFromScope(anyString())).thenCallRealMethod();

@Override
protected String serializeModelData() {
return "Dummy implementation";
}
SettingsService settingsService = mock(SettingsService.class);

ILocation mockProjectLocation = mock(ILocation.class);
ILocation mockProjectSettingsFolderLocation = mock(ILocation.class);
when(mockProjectLocation.append(".polarion/extensions/null/Test")).thenReturn(mockProjectSettingsFolderLocation);
ILocation mockProjectTest1Location = mock(ILocation.class);
when(mockProjectLocation.append(".polarion/extensions/null/Test/project_list_revisions1.settings")).thenReturn(mockProjectTest1Location);
ILocation mockProjectDefault1Location = mock(ILocation.class);
when(mockProjectLocation.append(".polarion/extensions/null/Test/default_list_revisions1.settings")).thenReturn(mockProjectDefault1Location);

mockScopeUtils.when(() -> ScopeUtils.getContextLocation("project/list_revisions_project/")).thenReturn(mockProjectLocation);
when(settingsService.getLastRevision(mockProjectSettingsFolderLocation)).thenReturn("11");
when(settingsService.getPersistedSettingFileNames(mockProjectSettingsFolderLocation)).thenReturn(List.of("project_list_revisions1"));

ILocation mockDefaultLocation = mock(ILocation.class);
ILocation mockDefaultSettingsFolderLocation = mock(ILocation.class);
when(mockDefaultLocation.append(".polarion/extensions/null/Test")).thenReturn(mockDefaultSettingsFolderLocation);
ILocation mockDefaultTest1Location = mock(ILocation.class);
when(mockDefaultLocation.append(".polarion/extensions/null/Test/default_list_revisions1.settings")).thenReturn(mockDefaultTest1Location);

mockScopeUtils.when(() -> ScopeUtils.getContextLocation("")).thenReturn(mockDefaultLocation);
when(settingsService.getLastRevision(mockDefaultSettingsFolderLocation)).thenReturn("66");
when(settingsService.getPersistedSettingFileNames(mockDefaultSettingsFolderLocation)).thenReturn(List.of("default_list_revisions1"));

@Override
protected void deserializeModelData(String serializedString) {
// Dummy implementation
TestSettings testSettings = new TestSettings(settingsService);
when(settingsService.read(eq(mockProjectTest1Location), any())).thenReturn(getModelContent("project_list_revisions1"));
when(settingsService.listRevisions(eq(mockProjectTest1Location), eq("list_revisions_project"))).thenReturn(
List.of(
Revision.builder().name("3").build(),
Revision.builder().name("2").build(),
Revision.builder().name("1").build()
)
);
when(settingsService.listRevisions(eq(mockProjectDefault1Location), eq("list_revisions_project"))).thenReturn(Collections.emptyList());
when(settingsService.listRevisions(eq(mockDefaultTest1Location), eq(null))).thenReturn(
List.of(
Revision.builder().name("5").build(),
Revision.builder().name("4").build()
)
);

when(settingsService.read(eq(mockDefaultTest1Location), any())).thenReturn(getModelContent("default_list_revisions1"));

assertThrows(ObjectNotFoundException.class, () -> {
testSettings.listRevisions("project/list_revisions_project/", SettingId.fromName("unknown"));
});

List<Revision> projectListRevisions1 = testSettings.listRevisions("project/list_revisions_project/", SettingId.fromName("project_list_revisions1"));
assertThat(projectListRevisions1).extracting(Revision::getName).containsExactly("3", "2", "1");

List<Revision> defaultListRevisions1 = testSettings.listRevisions("", SettingId.fromName("default_list_revisions1"));
assertThat(defaultListRevisions1).extracting(Revision::getName).containsExactly("5", "4");

List<Revision> projectDefaultListRevisions1 = testSettings.listRevisions("project/list_revisions_project/", SettingId.fromName("default_list_revisions1"));
assertThat(projectDefaultListRevisions1).isEmpty();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ch.sbb.polarion.extension.generic.settings.named_settings;

import ch.sbb.polarion.extension.generic.settings.SettingsModel;

public class TestModel extends SettingsModel {

@Override
protected String serializeModelData() {
return "Dummy implementation";
}

@Override
protected void deserializeModelData(String serializedString) {
// Dummy implementation
}
}
Loading

0 comments on commit defe5f0

Please sign in to comment.