Skip to content

Commit 9843651

Browse files
committed
Start writing ContainerGroupRepositoryImpl tests
1 parent 98f5f4a commit 9843651

File tree

5 files changed

+315
-5
lines changed

5 files changed

+315
-5
lines changed

java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/ContainerGroupRepositoryImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,8 @@ private void addModuleRoot(Location location, PathRoot pathRoot) {
354354

355355
if (modules.isEmpty()) {
356356
LOGGER.warn(
357-
"There were no valid modules present in {}, so nothing has been registered. "
358-
+ "If you are sure that there are files, this is probably a bug.",
359-
modules
357+
"There were no valid modules present in {}, so nothing has been registered.",
358+
pathRoot.getPath()
360359
);
361360
} else {
362361
var moduleGroup = getOrCreateModuleContainerGroup(location);

java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/helpers/Fixtures.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
*
5858
* @author Ashley Scopes
5959
*/
60-
@SuppressWarnings("NullableProblems")
6160
public final class Fixtures {
6261

6362
private static final Random RANDOM = new Random();
@@ -369,7 +368,22 @@ public static Location someLocation() {
369368
* @return some mock path root object.
370369
*/
371370
public static PathRoot somePathRoot() {
372-
return mock(PathRoot.class, "PathRoot-" + someText());
371+
var name = "PathRoot-" + someText();
372+
var path = someRelativePath().resolve(name);
373+
PathRoot pathRoot = mock(withSettings()
374+
.strictness(Strictness.LENIENT)
375+
.name(path.toString()));
376+
when(pathRoot.getPath()).thenReturn(path);
377+
when(pathRoot.getUri()).thenReturn(path.toUri());
378+
379+
try {
380+
when(pathRoot.getUrl()).thenReturn(path.toUri().toURL());
381+
} catch (Exception ex) {
382+
throw new IllegalStateException("unreachable", ex);
383+
}
384+
385+
when(pathRoot.getParent()).thenReturn(null);
386+
return pathRoot;
373387
}
374388

375389
/**
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/*
2+
* Copyright (C) 2022 - 2023, the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.github.ascopes.jct.tests.unit.containers.impl;
17+
18+
import static io.github.ascopes.jct.tests.helpers.Fixtures.somePathRoot;
19+
import static io.github.ascopes.jct.tests.helpers.Fixtures.someRelease;
20+
import static java.util.stream.Collectors.toMap;
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
import static org.assertj.core.api.InstanceOfAssertFactories.list;
23+
import static org.mockito.ArgumentMatchers.any;
24+
25+
import io.github.ascopes.jct.containers.Container;
26+
import io.github.ascopes.jct.containers.PackageContainerGroup;
27+
import io.github.ascopes.jct.containers.impl.ContainerGroupRepositoryImpl;
28+
import io.github.ascopes.jct.filemanagers.ModuleLocation;
29+
import io.github.ascopes.jct.utils.ModuleDiscoverer;
30+
import io.github.ascopes.jct.workspaces.PathRoot;
31+
import java.util.Map;
32+
import java.util.function.Function;
33+
import java.util.stream.Stream;
34+
import javax.tools.StandardLocation;
35+
import org.junit.jupiter.api.AfterEach;
36+
import org.junit.jupiter.api.BeforeEach;
37+
import org.junit.jupiter.api.DisplayName;
38+
import org.junit.jupiter.api.Nested;
39+
import org.junit.jupiter.api.Test;
40+
import org.junit.jupiter.api.extension.ExtendWith;
41+
import org.mockito.Answers;
42+
import org.mockito.Mock;
43+
import org.mockito.MockedStatic;
44+
import org.mockito.junit.jupiter.MockitoExtension;
45+
46+
/**
47+
* {@link ContainerGroupRepositoryImpl} tests.
48+
*
49+
* <p>This is partially an integration test in nature, but this is only done since there is
50+
* little benefit in mocking all moving components. Components that perform things like module
51+
* discovery will still be mocked internally. The idea behind this class is to ensure that the
52+
* implementation performs the expected behaviour as a pure black box (i.e. an opaque implementation
53+
* that may be subject to structural change over time).
54+
*
55+
* @author Ashley Scopes
56+
*/
57+
@DisplayName("ContainerGroupRepositoryImpl tests")
58+
@ExtendWith(MockitoExtension.class)
59+
@SuppressWarnings({"AssertBetweenInconvertibleTypes", "resource"})
60+
class ContainerGroupRepositoryImplTest {
61+
62+
String release;
63+
ContainerGroupRepositoryImpl repository;
64+
65+
@Mock(answer = Answers.RETURNS_SMART_NULLS)
66+
MockedStatic<ModuleDiscoverer> moduleDiscoverer;
67+
68+
@BeforeEach
69+
void setUp() {
70+
release = someRelease();
71+
repository = new ContainerGroupRepositoryImpl(release);
72+
}
73+
74+
@AfterEach
75+
void tearDown() {
76+
repository.close();
77+
}
78+
79+
@DisplayName("Initialising the repository sets the release")
80+
@Test
81+
void initialisingTheRepositorySetsTheRelease() {
82+
// Given
83+
var release = someRelease();
84+
try (var repository = new ContainerGroupRepositoryImpl(release)) {
85+
// Then
86+
assertThat(repository.getRelease()).isEqualTo(release);
87+
}
88+
}
89+
90+
@DisplayName(".addPath(...) tests")
91+
@Nested
92+
class AddPathTest {
93+
94+
@DisplayName("adding a module location in a non-existent parent registers the module correctly")
95+
@Test
96+
void addingModuleLocationInNonExistentParentRegistersModuleCorrectly() {
97+
// Given
98+
var moduleLocation = new ModuleLocation(StandardLocation.MODULE_SOURCE_PATH, "foo.bar");
99+
PathRoot pathRoot = somePathRoot();
100+
101+
// When
102+
repository.addPath(moduleLocation, pathRoot);
103+
104+
// Then
105+
var groups = repository.getModuleContainerGroups();
106+
assertThat(groups)
107+
.as("module oriented groups")
108+
.hasSize(1);
109+
110+
var group = groups.iterator().next();
111+
assertThat(group.getLocation())
112+
.as("module oriented group location")
113+
.isEqualTo(StandardLocation.MODULE_SOURCE_PATH);
114+
115+
var modules = group.getModules();
116+
assertThat(modules)
117+
.as("map of modules in module oriented group")
118+
.hasSize(1)
119+
.containsKey(moduleLocation);
120+
121+
var module = modules.get(moduleLocation);
122+
assertThat(module.getLocation())
123+
.as("module group location")
124+
.isEqualTo(moduleLocation);
125+
126+
var packages = module.getPackages();
127+
assertThat(packages)
128+
.as("collection of module group packages")
129+
.hasSize(1);
130+
131+
var modulePackage = packages.iterator().next();
132+
assertThat(modulePackage.getPathRoot())
133+
.as("module group package path root")
134+
.isEqualTo(pathRoot);
135+
}
136+
137+
@DisplayName("adding a package to a non-existent output group registers it as a package")
138+
@Test
139+
void addingPackageToNonExistentOutputGroupRegistersItAsPackage() {
140+
// Given
141+
var location = StandardLocation.CLASS_OUTPUT;
142+
PathRoot pathRoot = somePathRoot();
143+
144+
// When
145+
repository.addPath(location, pathRoot);
146+
147+
// Then
148+
var groups = repository.getOutputContainerGroups();
149+
assertThat(groups)
150+
.as("output container groups")
151+
.hasSize(1);
152+
153+
var group = groups.iterator().next();
154+
assertThat(group.getLocation())
155+
.as("output container group location")
156+
.isEqualTo(location);
157+
158+
assertThat(group.getModules())
159+
.as("output container group modules")
160+
.isEmpty();
161+
162+
var packages = group.getPackages();
163+
assertThat(packages)
164+
.as("output container group packages")
165+
.hasSize(1);
166+
167+
var outputPackage = packages.iterator().next();
168+
assertThat(outputPackage.getPathRoot())
169+
.as("output package path root")
170+
.isEqualTo(pathRoot);
171+
}
172+
173+
@DisplayName(
174+
"adding an empty directory to a module-oriented group does not register any modules"
175+
)
176+
@Test
177+
void addingEmptyDirectoryToModuleOrientedGroupDoesNotRegisterModules() {
178+
// Given
179+
var location = StandardLocation.MODULE_SOURCE_PATH;
180+
PathRoot pathRoot = somePathRoot();
181+
182+
moduleDiscoverer.when(() -> ModuleDiscoverer.findModulesIn(any()))
183+
.thenReturn(Map.of());
184+
185+
// When
186+
repository.addPath(location, pathRoot);
187+
188+
// Then
189+
var groups = repository.getModuleContainerGroups();
190+
assertThat(groups)
191+
.as("module container groups")
192+
.isEmpty();
193+
194+
moduleDiscoverer.verify(() -> ModuleDiscoverer.findModulesIn(pathRoot.getPath()));
195+
}
196+
197+
@DisplayName(
198+
"adding a directory of modules to a module-oriented group registers them as modules"
199+
)
200+
@Test
201+
void addingDirectoryOfModulesToModuleOrientedGroupRegistersThemAsModules() {
202+
// Given
203+
var location = StandardLocation.MODULE_SOURCE_PATH;
204+
PathRoot pathRoot = somePathRoot();
205+
206+
var discoveredModules = Stream.of("foo.bar", "baz.bork")
207+
.collect(toMap(
208+
Function.identity(),
209+
pathRoot.getPath()::resolve
210+
));
211+
212+
moduleDiscoverer.when(() -> ModuleDiscoverer.findModulesIn(any()))
213+
.thenReturn(discoveredModules);
214+
215+
// When
216+
repository.addPath(location, pathRoot);
217+
218+
// Then
219+
var groups = repository.getModuleContainerGroups();
220+
assertThat(groups)
221+
.as("module container groups")
222+
.hasSize(1);
223+
224+
var group = groups.iterator().next();
225+
assertThat(group.getLocation())
226+
.as("module container group location")
227+
.isEqualTo(location);
228+
229+
var modules = group.getModules();
230+
assertThat(modules)
231+
.as("module container group modules")
232+
.hasSize(2);
233+
234+
assertThat(modules.get(new ModuleLocation(StandardLocation.MODULE_SOURCE_PATH, "foo.bar")))
235+
.as("module container group module <foo.bar>")
236+
.extracting(PackageContainerGroup::getPackages, list(Container.class))
237+
.singleElement()
238+
.extracting(Container::getPathRoot)
239+
.extracting(PathRoot::getPath)
240+
.isEqualTo(pathRoot.getPath().resolve("foo.bar"));
241+
242+
assertThat(modules.get(new ModuleLocation(StandardLocation.MODULE_SOURCE_PATH, "baz.bork")))
243+
.as("module container group module <baz.bork>")
244+
.extracting(PackageContainerGroup::getPackages, list(Container.class))
245+
.singleElement()
246+
.extracting(Container::getPathRoot)
247+
.extracting(PathRoot::getPath)
248+
.isEqualTo(pathRoot.getPath().resolve("baz.bork"));
249+
250+
moduleDiscoverer.verify(() -> ModuleDiscoverer.findModulesIn(pathRoot.getPath()));
251+
}
252+
253+
@DisplayName("adding a package root registers the package root")
254+
@Test
255+
void addingPackageRootRegistersPackageRoot() {
256+
257+
}
258+
}
259+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (C) 2022 - 2023, the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
@NullMarked
17+
package io.github.ascopes.jct.tests.unit.containers.impl;
18+
19+
import org.jspecify.annotations.NullMarked;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (C) 2022 - 2023, the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
@NullMarked
17+
package io.github.ascopes.jct.tests.unit.containers;
18+
19+
import org.jspecify.annotations.NullMarked;

0 commit comments

Comments
 (0)