Skip to content

Commit

Permalink
refactor(test): made state creation process more extensible
Browse files Browse the repository at this point in the history
Refs: #64
  • Loading branch information
nergal-perm committed Sep 13, 2024
1 parent 148a319 commit fb5ea75
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 109 deletions.
83 changes: 35 additions & 48 deletions src/main/java/ru/ewc/checklogic/FileStateFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,15 @@
package ru.ewc.checklogic;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.SneakyThrows;
import org.yaml.snakeyaml.Yaml;
import ru.ewc.decisions.api.InMemoryLocator;
Expand All @@ -45,70 +44,58 @@
*
* @since 0.3.2
*/
public final class FileStateFactory extends StateFactory {
public final class FileStateFactory implements StateFactory {
/**
* An instance of server configuration.
*/
private final ServerConfiguration config;

/**
* Optional source of locators to be added to the initial (clean) state.
* The collection of all the state and functions locators.
*/
private InputStream src;
private final List<Locator> locators;

public FileStateFactory(final String root) {
super(root);
public FileStateFactory(final ServerConfiguration config) {
this.config = config;
this.locators = new ArrayList<>(1);
}

@Override
@SneakyThrows
public State initialState() {
State state;
try (InputStream file = Files.newInputStream(Path.of(this.getRoot(), "application.yaml"))) {
state = FileStateFactory.stateFromAppConfig(file);
state.locators().putAll(this.locatorsFromFile());
} catch (final NoSuchFileException exception) {
state = State.EMPTY;
}
return state;
this.locators.clear();
this.loadLocatorsFromApplicationConfig();
this.loadInMemoryRequestLocator();
return new State(this.locators);
}

@Override
public StateFactory with(final InputStream file) {
this.src = file;
return this;
private void loadInMemoryRequestLocator() {
this.locators.add(
new InMemoryLocator(this.config.requestLocatorName(), new HashMap<>())
);
}

@Override
@SneakyThrows
public void initialize() {
final File config = Path.of(this.getRoot(), "application.yaml").toFile();
if (!config.exists() && config.createNewFile()) {
try (OutputStream out = Files.newOutputStream(config.toPath())) {
private InputStream applicationConfigFile() {
final File fileconf = this.config.applicationConfig().toFile();
if (!fileconf.exists() && fileconf.createNewFile()) {
try (OutputStream out = Files.newOutputStream(fileconf.toPath())) {
out.write("locators:\n - request\n".getBytes(StandardCharsets.UTF_8));
}
}
return Files.newInputStream(this.config.applicationConfig());
}

@SuppressWarnings("unchecked")
private Map<String, Locator> locatorsFromFile() {
final Map<String, Locator> locators = new HashMap<>();
if (this.src != null) {
final Map<String, Map<String, Object>> raw =
(Map<String, Map<String, Object>>) new Yaml().loadAll(this.src).iterator().next();
if (raw == null) {
throw new IllegalStateException(
"There is no Arrange section in the test file, you should add one"
);
}
raw.forEach((name, data) -> locators.put(name, new InMemoryLocator(name, data)));
private void loadLocatorsFromApplicationConfig() {
try (InputStream file = this.applicationConfigFile()) {
final Map<String, Object> yaml = new Yaml().load(file);
this.locators.addAll(
((List<String>) yaml.get("locators")).stream()
.map(name -> new InMemoryLocator(name, new HashMap<>()))
.toList()
);
} catch (final IOException exception) {
this.locators.addAll(List.of());
}
return locators;
}

@SneakyThrows
@SuppressWarnings("unchecked")
private static State stateFromAppConfig(final InputStream file) {
final Map<String, Object> config = new Yaml().load(file);
return new State(((List<String>) config.get("locators")).stream()
.map(name -> new InMemoryLocator(name, new HashMap<>()))
.collect(Collectors.toList())
);
}
}
16 changes: 1 addition & 15 deletions src/main/java/ru/ewc/checklogic/MockStateFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
*/
package ru.ewc.checklogic;

import java.io.InputStream;
import java.util.List;
import java.util.Map;
import ru.ewc.decisions.api.InMemoryLocator;
Expand All @@ -34,11 +33,7 @@
*
* @since 0.3.2
*/
public final class MockStateFactory extends StateFactory {
public MockStateFactory(final String root) {
super(root);
}

public final class MockStateFactory implements StateFactory {
@Override
public State initialState() {
return new State(
Expand All @@ -49,13 +44,4 @@ public State initialState() {
);
}

@Override
public StateFactory with(final InputStream file) {
return this;
}

@Override
public void initialize() {
// do nothing
}
}
31 changes: 25 additions & 6 deletions src/main/java/ru/ewc/checklogic/ServerConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package ru.ewc.checklogic;

import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -32,15 +33,25 @@
* @since 0.3.2
*/
public final class ServerConfiguration {
/**
* The path to a root folder of the external business logic resources.
*/
private final String root;

/**
* The parameters of the context.
*/
private final Map<String, String> parameters = new HashMap<>(
Map.of(
"request", "request",
"command", "available"
)
);
private final Map<String, String> parameters;

public ServerConfiguration(final String root) {
this.root = root;
this.parameters = new HashMap<>(
Map.of(
"request", "request",
"command", "available"
)
);
}

/**
* Returns the value of the specified parameter.
Expand Down Expand Up @@ -69,4 +80,12 @@ public String commandAvailabilityField() {
public String requestLocatorName() {
return this.getParameterValue("request");
}

public Path applicationConfig() {
return Path.of(this.root, "application.yaml");
}

public String getRoot() {
return this.root;
}
}
12 changes: 7 additions & 5 deletions src/main/java/ru/ewc/checklogic/ServerContextFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,20 @@ private ServerContextFactory(
}

public static ServerContextFactory testable() {
final String path = "root folder";
return new ServerContextFactory(
"root folder",
new MockStateFactory("root folder"),
new ServerConfiguration()
path,
new MockStateFactory(),
new ServerConfiguration(path)
);
}

public static ServerContextFactory create(final String root) {
final ServerConfiguration config = new ServerConfiguration(root);
return new ServerContextFactory(
root,
new FileStateFactory(root),
new ServerConfiguration()
new FileStateFactory(config),
config
);
}

Expand Down
3 changes: 1 addition & 2 deletions src/main/java/ru/ewc/checklogic/ServerInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public final class ServerInstance {
final ServerConfiguration server) {
this.states = initial;
this.server = server;
this.root = this.states.getRoot();
this.root = this.server.getRoot();
this.state = this.states.initialState();
this.tables = tables;
this.context = new ComputationContext(this.state, this.getAllTables());
Expand Down Expand Up @@ -153,7 +153,6 @@ public String getRoot() {
}

public void initialize() {
this.states.initialize();
this.state = this.states.initialState();
this.context = new ComputationContext(this.state, this.getAllTables());
}
Expand Down
27 changes: 2 additions & 25 deletions src/main/java/ru/ewc/checklogic/StateFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
*/
package ru.ewc.checklogic;

import java.io.InputStream;
import ru.ewc.state.State;

/**
Expand All @@ -33,28 +32,6 @@
*
* @since 0.3.2
*/
public abstract class StateFactory {
/**
* The root path for the external business logic resources.
*/
private final String root;

public StateFactory(final String root) {
this.root = root;
}

/**
* Returns the path to the root folder of the external business logic resources.
*
* @return Path to the root folder as a string.
*/
public String getRoot() {
return this.root;
}

public abstract State initialState();

public abstract StateFactory with(InputStream file);

public abstract void initialize();
interface StateFactory {
State initialState();
}
6 changes: 5 additions & 1 deletion src/main/java/ru/ewc/checklogic/server/WebPages.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ public WebPages(
}

public static WebPages testable() {
return new WebPages(new MockTemplateRender(), "root folder", new ServerConfiguration());
return new WebPages(
new MockTemplateRender(),
"root folder",
new ServerConfiguration("root folder")
);
}

public Response uninitializedPage() {
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/ru/ewc/checklogic/ServerConfigurationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
final class ServerConfigurationTest {
@Test
void emptyServerContextHasDefaultRequestLocatorName() {
final ServerConfiguration context = new ServerConfiguration();
final ServerConfiguration context = new ServerConfiguration("any");
MatcherAssert.assertThat(
"New server context should have 'request' as default incoming request locator's name",
context.getParameterValue("request"),
Expand All @@ -45,7 +45,7 @@ void emptyServerContextHasDefaultRequestLocatorName() {

@Test
void emptyServerContextHasDefaultCommandAvailabilityOutcome() {
final ServerConfiguration context = new ServerConfiguration();
final ServerConfiguration context = new ServerConfiguration("any");
MatcherAssert.assertThat(
"New server context should have 'available' as default command availability outcome",
context.getParameterValue("command"),
Expand All @@ -55,7 +55,7 @@ void emptyServerContextHasDefaultCommandAvailabilityOutcome() {

@Test
void shouldUpdateRequestLocatorName() {
final ServerConfiguration context = new ServerConfiguration();
final ServerConfiguration context = new ServerConfiguration("any");
context.setParameterValue("request", "incoming");
MatcherAssert.assertThat(
"Context server should update its incoming request locator's name",
Expand All @@ -66,7 +66,7 @@ void shouldUpdateRequestLocatorName() {

@Test
void shouldUpdateCommandAvailabilityOutcome() {
final ServerConfiguration context = new ServerConfiguration();
final ServerConfiguration context = new ServerConfiguration("any");
context.setParameterValue("command", "enabled");
MatcherAssert.assertThat(
"Context server should update its command availability outcome",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ final class ContextPageTest {
void shouldCreateMockServer() {
final ContextPage target = new ContextPage(
ServerInstance.testable(),
new ServerConfiguration()
new ServerConfiguration("any")
);
final Response response = target.contextPage(ServerTestObjects.emptyRequest());
MatcherAssert.assertThat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
final class ConfigPageTest {
@Test
void shouldNotUpdateParametersNotPresentInTheRequest() {
final ConfigPage target = new ConfigPage(new ServerConfiguration());
final ConfigPage target = new ConfigPage(new ServerConfiguration("any"));
target.updateParametersFrom(ServerTestObjects.emptyRequest());
MatcherAssert.assertThat(
"Parameters should not be updated if the Request is empty",
Expand Down
1 change: 0 additions & 1 deletion src/test/resources/tic-tac-toe/application.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
locators:
- request
- table
- cells

0 comments on commit fb5ea75

Please sign in to comment.