diff options
author | Håkon Hallingstad <hakon@oath.com> | 2018-11-23 17:30:13 +0100 |
---|---|---|
committer | Håkon Hallingstad <hakon@oath.com> | 2018-11-23 17:30:13 +0100 |
commit | cadcac9a8c0501f86372eb05d107d7b089643d0a (patch) | |
tree | 9593cc78763cba8e790e49c21f28a19182002765 /flags/src/test | |
parent | f67aa7bfa1553d8cc19ce4eef96f42ff8c31a320 (diff) |
Add flags module
FileFlagSource reads flags from files in /etc/vespa/flags and is a component
that can be injected in host admin, config server, etc. A flag named foo
corresponds to filename foo.
In general a FlagSource manages:
- Feature flags: A feature is either set (true/enabled) or otherwise false.
Touching a file foo means the feature flag foo is set (true).
- Value flags: Either a String or empty if not set. The String corresponds to
the file content.
The plan is to make the config server another source of flags. A unified
FlagSource can merge the two sources with some priority and used in e.g. parts
of node-admin. In other parts one would only have access to the file source.
Defines various flag facades:
- FeatureFlag: Used to test whether a feature has been enabled or not.
- IntFlag
- JacksonFlag: Deserializes JSON to Jackson class, or return default if unset.
- LongFlag
- OptionalJacksonFlag: Deserializes JSON to Jackson class, or empty if unset.
- OptionalStringFlag
- StringFlag
This is part of removing some of the last Chef recipes. Some minor tweaks have
been necessary as part of this and are included in this PR (test whether a
systemd service exists, task-friendly file deletion, allow capitalized letters
in YUM package name).
Diffstat (limited to 'flags/src/test')
-rw-r--r-- | flags/src/test/java/com/yahoo/vespa/flags/FileFlagSourceTest.java | 49 | ||||
-rw-r--r-- | flags/src/test/java/com/yahoo/vespa/flags/JacksonFlagTest.java | 72 |
2 files changed, 121 insertions, 0 deletions
diff --git a/flags/src/test/java/com/yahoo/vespa/flags/FileFlagSourceTest.java b/flags/src/test/java/com/yahoo/vespa/flags/FileFlagSourceTest.java new file mode 100644 index 00000000000..e422057f5fe --- /dev/null +++ b/flags/src/test/java/com/yahoo/vespa/flags/FileFlagSourceTest.java @@ -0,0 +1,49 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.flags; + +import com.yahoo.vespa.test.file.TestFileSystem; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class FileFlagSourceTest { + private final FileSystem fileSystem = TestFileSystem.create(); + private final FileFlagSource source = new FileFlagSource(fileSystem); + + @Test + public void absentThenSet() throws IOException { + FlagId id = new FlagId("foo"); + FeatureFlag featureFlag = new FeatureFlag(id, source); + StringFlag stringFlag = new StringFlag(id, "default", source); + OptionalStringFlag optionalStringFlag = new OptionalStringFlag(id, source); + IntFlag intFlag = new IntFlag(id, -1, source); + LongFlag longFlag = new LongFlag(id, -2L, source); + + assertFalse(source.hasFeature(id)); + assertFalse(source.getString(id).isPresent()); + assertFalse(featureFlag.isSet()); + assertEquals("default", stringFlag.value()); + assertFalse(optionalStringFlag.value().isPresent()); + assertEquals(-1, intFlag.value()); + assertEquals(-2L, longFlag.value()); + + Path featurePath = fileSystem.getPath(FileFlagSource.FLAGS_DIRECTORY).resolve(id.toString()); + Files.createDirectories(featurePath.getParent()); + Files.write(featurePath, "1\n".getBytes()); + + assertTrue(source.hasFeature(id)); + assertTrue(source.getString(id).isPresent()); + assertTrue(featureFlag.isSet()); + assertEquals("1\n", stringFlag.value()); + assertEquals("1\n", optionalStringFlag.value().get()); + assertEquals(1, intFlag.value()); + assertEquals(1L, longFlag.value()); + } +}
\ No newline at end of file diff --git a/flags/src/test/java/com/yahoo/vespa/flags/JacksonFlagTest.java b/flags/src/test/java/com/yahoo/vespa/flags/JacksonFlagTest.java new file mode 100644 index 00000000000..e4424d9886a --- /dev/null +++ b/flags/src/test/java/com/yahoo/vespa/flags/JacksonFlagTest.java @@ -0,0 +1,72 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.flags; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.junit.Test; + +import java.util.Objects; +import java.util.Optional; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class JacksonFlagTest { + private final FlagId id = new FlagId("id"); + private final ExampleJacksonClass defaultValue = new ExampleJacksonClass(); + private final FlagSource source = mock(FlagSource.class); + private final JacksonFlag<ExampleJacksonClass> jacksonFlag = new JacksonFlag<>(id.toString(), ExampleJacksonClass.class, defaultValue, source); + private final OptionalJacksonFlag<ExampleJacksonClass> optionalJacksonFlag = new OptionalJacksonFlag<>(id, ExampleJacksonClass.class, source); + + @Test + public void unsetThenSet() { + when(source.getString(id)).thenReturn(Optional.empty()); + ExampleJacksonClass value = jacksonFlag.value(); + assertEquals(1, value.integer); + assertEquals("2", value.string); + assertEquals("3", value.dummy); + assertFalse(optionalJacksonFlag.value().isPresent()); + + when(source.getString(id)).thenReturn(Optional.of("{\"integer\": 4, \"string\": \"foo\", \"stray\": 6}")); + value = jacksonFlag.value(); + assertEquals(4, value.integer); + assertEquals("foo", value.string); + assertEquals("3", value.dummy); + + assertTrue(optionalJacksonFlag.value().isPresent()); + value = optionalJacksonFlag.value().get(); + assertEquals(4, value.integer); + assertEquals("foo", value.string); + assertEquals("3", value.dummy); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + private static class ExampleJacksonClass { + @JsonProperty("integer") + public int integer = 1; + + @JsonProperty("string") + public String string = "2"; + + @JsonProperty("dummy") + public String dummy = "3"; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ExampleJacksonClass that = (ExampleJacksonClass) o; + return integer == that.integer && + Objects.equals(string, that.string) && + Objects.equals(dummy, that.dummy); + } + + @Override + public int hashCode() { + return Objects.hash(integer, string, dummy); + } + } +}
\ No newline at end of file |