DataConflationSender: Add initial tests

Signed-off-by: Taylor Smock <tsmock@fb.com>
pull/1/head
Taylor Smock 2021-11-10 17:07:44 -07:00
rodzic 99f4de5dd4
commit 9f424eaaa2
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 625F6A74A3E4311A
6 zmienionych plików z 217 dodań i 41 usunięć

Wyświetl plik

@ -1,6 +1,12 @@
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.mapwithai.backend;
import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonValue;
import javax.json.stream.JsonParser;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@ -13,12 +19,6 @@ import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonValue;
import javax.json.stream.JsonParser;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.io.CachedFile;
@ -157,8 +157,7 @@ public class DataAvailability {
* @return the unique instance
*/
public static DataAvailability getInstance() {
if (instance == null || COUNTRIES.isEmpty()
|| MapWithAIPreferenceHelper.getMapWithAIUrl().isEmpty()) {
if (instance == null || COUNTRIES.isEmpty() || MapWithAIPreferenceHelper.getMapWithAIUrl().isEmpty()) {
instance = new DataAvailability();
}
return instance;

Wyświetl plik

@ -31,6 +31,7 @@ import org.openstreetmap.josm.io.OsmWriterFactory;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAICategory;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIConflationCategory;
import org.openstreetmap.josm.tools.Logging;
import org.openstreetmap.josm.tools.Utils;
/**
* Conflate data with a third party server
@ -66,6 +67,7 @@ public class DataConflationSender implements RunnableFuture<DataSet> {
@Override
public void run() {
String url = MapWithAIConflationCategory.conflationUrlFor(category);
if (!Utils.isBlank(url)) {
this.client = HttpClients.createDefault();
try (CloseableHttpClient currentClient = this.client) {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
@ -73,7 +75,8 @@ public class DataConflationSender implements RunnableFuture<DataSet> {
StringWriter output = new StringWriter();
try (OsmWriter writer = OsmWriterFactory.createOsmWriter(new PrintWriter(output), true, "0.6")) {
writer.write(osm);
multipartEntityBuilder.addTextBody("openstreetmap", output.toString(), ContentType.APPLICATION_XML);
multipartEntityBuilder.addTextBody("openstreetmap", output.toString(),
ContentType.APPLICATION_XML);
}
}
// We need to reset the writers to avoid writing previous streams
@ -87,19 +90,19 @@ public class DataConflationSender implements RunnableFuture<DataSet> {
HttpResponse response = currentClient.execute(request);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
conflatedData = OsmReader.parseDataSet(response.getEntity().getContent(), NullProgressMonitor.INSTANCE,
OsmReader.Options.SAVE_ORIGINAL_ID);
conflatedData = OsmReader.parseDataSet(response.getEntity().getContent(),
NullProgressMonitor.INSTANCE, OsmReader.Options.SAVE_ORIGINAL_ID);
} else {
conflatedData = null;
}
ProtocolVersion protocolVersion = response.getStatusLine().getProtocolVersion();
Logging.info(new StringBuilder(request.getMethod()).append(' ').append(url).append(" -> ")
.append(protocolVersion.getProtocol()).append('/').append(protocolVersion.getMajor()).append('.')
.append(protocolVersion.getMinor()).append(' ').append(response.getStatusLine().getStatusCode())
.toString());
Logging.info(request.getMethod() + ' ' + url + " -> " + protocolVersion.getProtocol() + '/'
+ protocolVersion.getMajor() + '.' + protocolVersion.getMinor() + ' '
+ response.getStatusLine().getStatusCode());
} catch (IOException | UnsupportedOperationException | IllegalDataException e) {
Logging.error(e);
}
}
this.done = true;
synchronized (this) {
this.notifyAll();

Wyświetl plik

@ -3,6 +3,9 @@ package org.openstreetmap.josm.plugins.mapwithai.data.mapwithai;
import static org.openstreetmap.josm.tools.I18n.tr;
import javax.annotation.Nonnull;
import javax.swing.SwingUtilities;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@ -20,9 +23,6 @@ import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.swing.SwingUtilities;
import org.openstreetmap.gui.jmapviewer.tilesources.TileSourceInfo;
import org.openstreetmap.josm.actions.ExpertToggleAction;
import org.openstreetmap.josm.data.Preferences;

Wyświetl plik

@ -0,0 +1,157 @@
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.mapwithai.backend;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.api.function.ThrowingSupplier;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAICategory;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIConflationCategory;
import org.openstreetmap.josm.plugins.mapwithai.testutils.annotations.MapWithAISources;
import org.openstreetmap.josm.plugins.mapwithai.testutils.annotations.Wiremock;
import org.openstreetmap.josm.testutils.JOSMTestRules;
import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import mockit.Invocation;
import mockit.Mock;
import mockit.MockUp;
/**
* Test class for {@link DataConflationSender}
*
* @author Taylor Smock
*/
@BasicPreferences
@Wiremock
@MapWithAISources
class DataConflationSenderTest {
// Needed for HTTP factory
@RegisterExtension
JOSMTestRules josmTestRules = new JOSMTestRules();
@BasicWiremock
WireMockServer wireMockServer;
static class MapWithAIConflationCategoryMock extends MockUp<MapWithAIConflationCategory> {
static String url;
@Mock
public static String conflationUrlFor(final Invocation invocation, final MapWithAICategory category) {
if (url == null) {
return invocation.proceed(category);
} else {
return url;
}
}
}
@BeforeEach
void beforeEach() {
MapWithAIConflationCategoryMock.url = null;
}
@Test
void testEmptyUrl() {
MapWithAIConflationCategoryMock.url = "";
new MapWithAIConflationCategoryMock();
final DataSet external = new DataSet(new Node(LatLon.NORTH_POLE));
final DataSet openstreetmap = new DataSet(new Node(LatLon.ZERO));
final DataConflationSender dataConflationSender = new DataConflationSender(MapWithAICategory.OTHER,
openstreetmap, external);
dataConflationSender.run();
assertNull(assertDoesNotThrow((ThrowingSupplier<DataSet>) dataConflationSender::get));
}
@Test
void testWorkingUrl() {
MapWithAIConflationCategoryMock.url = wireMockServer.baseUrl() + "/conflate";
final StubMapping stubMapping = wireMockServer
.stubFor(WireMock.post("/conflate").willReturn(WireMock.aResponse().withBody(
"<?xml version='1.0' encoding='UTF-8'?><osm version='0.6' generator='DataConflationSenderTest#testWorkingUrl'><node id='1' version='1' visible='true' lat='89.0' lon='0.1' /></osm>")));
new MapWithAIConflationCategoryMock();
final DataSet external = new DataSet(new Node(LatLon.NORTH_POLE));
final DataSet openstreetmap = new DataSet(new Node(LatLon.ZERO));
final DataConflationSender dataConflationSender = new DataConflationSender(MapWithAICategory.OTHER,
openstreetmap, external);
dataConflationSender.run();
final DataSet conflated = assertDoesNotThrow((ThrowingSupplier<DataSet>) dataConflationSender::get);
assertNotNull(conflated);
assertEquals(1, conflated.allPrimitives().size());
assertEquals(1, conflated.getNodes().size());
final Node conflatedNode = conflated.getNodes().iterator().next();
assertEquals(new LatLon(89, 0.1), conflatedNode.getCoor());
assertEquals(1, wireMockServer.getAllServeEvents().stream()
.filter(serveEvent -> stubMapping.equals(serveEvent.getStubMapping())).count());
}
@Test
void testWorkingUrlTimeout() {
MapWithAIConflationCategoryMock.url = wireMockServer.baseUrl() + "/conflate";
final StubMapping stubMapping = wireMockServer.stubFor(WireMock.post("/conflate")
.willReturn(WireMock.aResponse().withBody(
"<?xml version='1.0' encoding='UTF-8'?><osm version='0.6' generator='DataConflationSenderTest#testWorkingUrl'><node id='1' version='1' visible='true' lat='89.0' lon='0.1' /></osm>")
.withFixedDelay(500)));
new MapWithAIConflationCategoryMock();
final DataSet external = new DataSet(new Node(LatLon.NORTH_POLE));
final DataSet openstreetmap = new DataSet(new Node(LatLon.ZERO));
final DataConflationSender dataConflationSender = new DataConflationSender(MapWithAICategory.OTHER,
openstreetmap, external);
MainApplication.worker.execute(dataConflationSender);
final DataSet conflated = assertDoesNotThrow(() -> dataConflationSender.get(1, TimeUnit.MILLISECONDS));
assertNotNull(conflated);
assertEquals(1, conflated.allPrimitives().size());
assertEquals(1, conflated.getNodes().size());
final Node conflatedNode = conflated.getNodes().iterator().next();
assertEquals(new LatLon(89, 0.1), conflatedNode.getCoor());
assertEquals(1, wireMockServer.getAllServeEvents().stream()
.filter(serveEvent -> stubMapping.equals(serveEvent.getStubMapping())).count());
}
static Stream<Arguments> testNonWorkingUrl() {
return Stream.of(Arguments.of(WireMock.noContent()), Arguments.of(WireMock.notFound()),
Arguments.of(WireMock.forbidden()), Arguments.of(WireMock.serverError()),
Arguments.of(WireMock.unauthorized()));
}
@ParameterizedTest
@MethodSource
void testNonWorkingUrl(final ResponseDefinitionBuilder response) {
MapWithAIConflationCategoryMock.url = wireMockServer.baseUrl() + "/conflate";
final StubMapping stubMapping = wireMockServer.stubFor(WireMock.post("/conflate").willReturn(response));
new MapWithAIConflationCategoryMock();
final DataSet external = new DataSet(new Node(LatLon.NORTH_POLE));
final DataSet openstreetmap = new DataSet(new Node(LatLon.ZERO));
final DataConflationSender dataConflationSender = new DataConflationSender(MapWithAICategory.OTHER,
openstreetmap, external);
dataConflationSender.run();
final DataSet conflated = assertDoesNotThrow((ThrowingSupplier<DataSet>) dataConflationSender::get);
assertNull(conflated);
assertEquals(1, wireMockServer.getAllServeEvents().stream()
.filter(serveEvent -> stubMapping.equals(serveEvent.getStubMapping())).count());
}
}

Wyświetl plik

@ -6,10 +6,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JCheckBox;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.openstreetmap.josm.data.Bounds;

Wyświetl plik

@ -26,6 +26,7 @@ import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
import org.openstreetmap.josm.testutils.annotations.HTTP;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.common.FileSource;
import com.github.tomakehurst.wiremock.extension.Parameters;
import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
@ -71,6 +72,7 @@ public @interface Wiremock {
@Override
public Response transform(Request request, Response response, FileSource files, Parameters parameters) {
if (!request.getUrl().endsWith("/capabilities")
&& response.getHeaders().getContentTypeHeader().mimeTypePart() != null
&& !response.getHeaders().getContentTypeHeader().mimeTypePart().contains("application/zip")) {
String origBody = response.getBodyAsString();
String newBody = origBody.replaceAll("https?://.*?/",
@ -152,6 +154,7 @@ public @interface Wiremock {
public String getMapWithAIPaintStyle() {
return replaceUrl(getWiremock(this.context), MapWithAIUrls.getInstance().getMapWithAIPaintStyle());
}
@Override
public void beforeAll(ExtensionContext context) throws Exception {
super.beforeAll(context);
@ -171,10 +174,20 @@ public @interface Wiremock {
@Override
public void beforeEach(ExtensionContext context) throws Exception {
final Optional<Wiremock> annotation = AnnotationUtils.findFirstParentAnnotation(context, Wiremock.class);
this.context = context;
if (annotation.isPresent()) {
this.beforeAll(context);
}
final WireMockServer wireMockServer = getWiremock(context);
super.beforeEach(context);
if (wireMockServer.getStubMappings().stream().filter(mapping -> mapping.getRequest().getUrl() != null)
.noneMatch(mapping -> mapping.getRequest().getUrl()
.equals("/JOSM_MapWithAI/json/conflation_servers.json"))) {
wireMockServer.stubFor(WireMock.get("/JOSM_MapWithAI/json/conflation_servers.json")
.willReturn(WireMock.aResponse().withBody("{}")).atPriority(-5));
}
}
@Override
@ -189,6 +202,10 @@ public @interface Wiremock {
MapWithAIConfig.setUrlsProvider(new InvalidMapWithAIUrls());
}
}
public WireMockServer getWireMockServer() {
return getWiremock(context);
}
}
class InvalidMapWithAIUrls implements IMapWithAIUrls {