diff --git a/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/dto/AdditionalInfoDto.java b/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/dto/AdditionalInfoDto.java index 07b74c4152..64e4e329da 100644 --- a/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/dto/AdditionalInfoDto.java +++ b/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/dto/AdditionalInfoDto.java @@ -65,4 +65,6 @@ public class AdditionalInfoDto { * a list of external service info which is direct to default WM */ public List employedDefaultWM = new ArrayList<>(); + + public List hostnameInfoDtos = new ArrayList<>(); } diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java index da7d89798a..5ecae0f389 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java @@ -526,6 +526,12 @@ public Response getTestResults( info.lastExecutedStatement = a.getLastExecutedStatement(); info.rawAccessOfHttpBodyPayload = a.isRawAccessOfHttpBodyPayload(); info.parsedDtoNames = new HashSet<>(a.getParsedDtoNamesView()); + info.hostnameInfoDtos = a.getHostnameInfos().stream() + .map(hn -> new HostnameInfoDto( + hn.getHostname(), + hn.getResolved() + )) + .collect(Collectors.toList()); info.externalServices = a.getExternalServices().stream() .map(es -> new ExternalServiceInfoDto( es.getProtocol(), diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java index 7d4f6b070a..924129e39d 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java @@ -1265,6 +1265,8 @@ protected BootTimeInfoDto getBootTimeInfoDto(BootTimeObjectiveInfo info){ value = e.getValue(); }}).collect(Collectors.toList()); + infoDto.hostnameInfoDtos = info.getHostnameInfos().stream() + .map(h -> new HostnameInfoDto(h.getHostname(), h.getResolved())).collect(Collectors.toList()); infoDto.externalServicesDto = info.getExternalServiceInfo().stream() .map(e -> new ExternalServiceInfoDto(e.getProtocol(), e.getHostname(), e.getRemotePort())) .collect(Collectors.toList()); diff --git a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/AdditionalInfo.java b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/AdditionalInfo.java index a98644203d..b03ec543d2 100644 --- a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/AdditionalInfo.java +++ b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/AdditionalInfo.java @@ -271,6 +271,10 @@ public void addHostnameInfo(HostnameInfo hostnameInfo) { hostnameInfos.add(hostnameInfo); } + public Set getHostnameInfos() { + return Collections.unmodifiableSet(hostnameInfos); + } + public Set getExternalServices() { return Collections.unmodifiableSet(externalServices); } diff --git a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/BootTimeObjectiveInfo.java b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/BootTimeObjectiveInfo.java index 73cbc2e3af..1c650210e6 100644 --- a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/BootTimeObjectiveInfo.java +++ b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/BootTimeObjectiveInfo.java @@ -36,11 +36,18 @@ public class BootTimeObjectiveInfo implements Serializable { */ private final List externalServiceInfo = new CopyOnWriteArrayList<>(); + private final List hostnameInfos = new CopyOnWriteArrayList<>(); + public void reset(){ maxObjectiveCoverage.clear(); externalServiceInfo.clear(); } + public void registerHostnameInfoAtSutBootTime(HostnameInfo hostnameInfo) { + if (hostnameInfos.isEmpty() || hostnameInfos.stream().noneMatch(h -> h.equals(hostnameInfo))) { + hostnameInfos.add(hostnameInfo.copy()); + } + } public void registerExternalServiceInfoAtSutBootTime(ExternalServiceInfo info){ if (externalServiceInfo.isEmpty() || externalServiceInfo.stream().noneMatch(s-> s.equals(info))) @@ -56,6 +63,10 @@ public List getExternalServiceInfo(){ return Collections.unmodifiableList(externalServiceInfo); } + public List getHostnameInfos() { + return Collections.unmodifiableList(hostnameInfos); + } + public void updateMaxObjectiveCoverage(String descriptiveId, double value){ Double h = maxObjectiveCoverage.get(descriptiveId); if (h == null || value > h) diff --git a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/HostnameInfo.java b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/HostnameInfo.java index 24fddf9ac0..7630434ac5 100644 --- a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/HostnameInfo.java +++ b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/HostnameInfo.java @@ -1,6 +1,7 @@ package org.evomaster.client.java.instrumentation; import java.io.Serializable; +import java.util.Objects; public class HostnameInfo implements Serializable { private final String remoteHostname; @@ -22,4 +23,22 @@ public String getHostname() { public Boolean getResolved() { return resolved; } + + public HostnameInfo copy(){ + return new HostnameInfo(remoteHostname, resolved); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HostnameInfo that = (HostnameInfo) o; + return Objects.equals(remoteHostname, that.remoteHostname); + } + + @Override + public int hashCode() { + // TODO: Excluded resolved from equals and hashCode, have to verify + return Objects.hash(remoteHostname); + } } diff --git a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/coverage/methodreplacement/classes/InetAddressClassReplacement.java b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/coverage/methodreplacement/classes/InetAddressClassReplacement.java index bf70415785..8b89724dac 100644 --- a/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/coverage/methodreplacement/classes/InetAddressClassReplacement.java +++ b/client-java/instrumentation/src/main/java/org/evomaster/client/java/instrumentation/coverage/methodreplacement/classes/InetAddressClassReplacement.java @@ -47,12 +47,12 @@ public static InetAddress getByName(String host) throws UnknownHostException { ExecutionTracer.addHostnameInfo(new HostnameInfo(host, true)); return inetAddress; } catch (UnknownHostException e) { - ExternalServiceInfo remoteHostInfo = new ExternalServiceInfo( - ExternalServiceSharedUtils.DEFAULT_SOCKET_CONNECT_PROTOCOL, - host, - -1 - ); - ExecutionTracer.addExternalServiceHost(remoteHostInfo); +// ExternalServiceInfo remoteHostInfo = new ExternalServiceInfo( +// ExternalServiceSharedUtils.DEFAULT_SOCKET_CONNECT_PROTOCOL, +// host, +// -1 +// ); +// ExecutionTracer.addExternalServiceHost(remoteHostInfo); ExecutionTracer.addHostnameInfo(new HostnameInfo(host, false)); throw e; } @@ -77,13 +77,13 @@ public static InetAddress[] getAllByName(String host) throws UnknownHostExceptio ExecutionTracer.addHostnameInfo(new HostnameInfo(host, true)); return inetAddresses; } catch (UnknownHostException e) { - ExternalServiceInfo remoteHostInfo = new ExternalServiceInfo( - ExternalServiceSharedUtils.DEFAULT_SOCKET_CONNECT_PROTOCOL, - host, - -1 - ); +// ExternalServiceInfo remoteHostInfo = new ExternalServiceInfo( +// ExternalServiceSharedUtils.DEFAULT_SOCKET_CONNECT_PROTOCOL, +// host, +// -1 +// ); +// ExecutionTracer.addExternalServiceHost(remoteHostInfo); ExecutionTracer.addHostnameInfo(new HostnameInfo(host, false)); - ExecutionTracer.addExternalServiceHost(remoteHostInfo); throw e; } } diff --git a/core/src/main/kotlin/org/evomaster/core/problem/externalservice/DomainNameAction.kt b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/HostnameAction.kt similarity index 81% rename from core/src/main/kotlin/org/evomaster/core/problem/externalservice/DomainNameAction.kt rename to core/src/main/kotlin/org/evomaster/core/problem/externalservice/HostnameAction.kt index 6910e6affb..5335c533c0 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/externalservice/DomainNameAction.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/HostnameAction.kt @@ -4,7 +4,7 @@ import org.evomaster.core.search.EnvironmentAction import org.evomaster.core.search.StructuralElement import org.evomaster.core.search.gene.Gene -class DomainNameAction : EnvironmentAction(listOf()) { +class HostnameAction : EnvironmentAction(listOf()) { override fun getName(): String { return "" } @@ -14,7 +14,7 @@ class DomainNameAction : EnvironmentAction(listOf()) { } override fun copyContent(): StructuralElement { - return DomainNameAction() + return HostnameAction() } } diff --git a/core/src/main/kotlin/org/evomaster/core/problem/externalservice/HostnameInfo.kt b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/HostnameInfo.kt index 58a586fea0..1e0cccef2f 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/externalservice/HostnameInfo.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/HostnameInfo.kt @@ -3,5 +3,4 @@ package org.evomaster.core.problem.externalservice open class HostnameInfo ( val remoteHostName: String, val resolved: Boolean -) { -} +) diff --git a/core/src/main/kotlin/org/evomaster/core/problem/externalservice/LocalDomainNameMapping.kt b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/LocalDomainNameMapping.kt new file mode 100644 index 0000000000..6ed6e788cd --- /dev/null +++ b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/LocalDomainNameMapping.kt @@ -0,0 +1,8 @@ +package org.evomaster.core.problem.externalservice + +import org.evomaster.core.problem.externalservice.HostnameInfo + +open class LocalDomainNameMapping( + val remoteHostnameInfo: HostnameInfo, + val localIP: String +) diff --git a/core/src/main/kotlin/org/evomaster/core/problem/externalservice/httpws/service/HttpWsExternalServiceHandler.kt b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/httpws/service/HttpWsExternalServiceHandler.kt index f79d059983..8e0ea6d872 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/externalservice/httpws/service/HttpWsExternalServiceHandler.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/externalservice/httpws/service/HttpWsExternalServiceHandler.kt @@ -7,6 +7,7 @@ import org.evomaster.core.EMConfig import org.evomaster.core.Lazy import org.evomaster.core.problem.externalservice.ExternalService import org.evomaster.core.problem.externalservice.HostnameInfo +import org.evomaster.core.problem.externalservice.LocalDomainNameMapping import org.evomaster.core.problem.externalservice.httpws.* import org.evomaster.core.problem.externalservice.httpws.HttpWsExternalServiceUtils.generateRandomIPAddress import org.evomaster.core.problem.externalservice.httpws.HttpWsExternalServiceUtils.isAddressAvailable @@ -57,7 +58,7 @@ class HttpWsExternalServiceHandler { * Map from hostname (used in SUT for external services) and local ip addresses, that we resolve * those hostname (ie like DNS) */ - private val localAddressMapping: MutableMap = mutableMapOf() +// private val localAddressMapping: MutableMap = mutableMapOf() /** * Skipped external services information provided through the driver to skip from @@ -65,8 +66,10 @@ class HttpWsExternalServiceHandler { */ private val skippedExternalServices: MutableList = mutableListOf() - - private val hostnames: MutableList = mutableListOf() + /** + * Map of remote hostname vs local DNS replacement + */ + private val hostnameMapping: MutableMap = mutableMapOf() /** * Contains last used loopback address for reference when creating @@ -95,6 +98,7 @@ class HttpWsExternalServiceHandler { private fun initDefaultWM() { if (config.externalServiceIPSelectionStrategy != EMConfig.ExternalServiceIPSelectionStrategy.NONE) { if (!isDefaultInitialized) { + addHostname(HostnameInfo("no_host_name", true)) registerHttpExternalServiceInfo(DefaultHttpExternalServiceInfo.createDefaultHttps()) registerHttpExternalServiceInfo(DefaultHttpExternalServiceInfo.createDefaultHttp()) isDefaultInitialized = true @@ -116,7 +120,11 @@ class HttpWsExternalServiceHandler { fun addHostname(hostnameInfo: HostnameInfo) { if (config.externalServiceIPSelectionStrategy != EMConfig.ExternalServiceIPSelectionStrategy.NONE) { - hostnames.add(hostnameInfo); + if (!hostnameMapping.containsKey(hostnameInfo.remoteHostName)) { + val ip = getNewIP() + lastIPAddress = ip + hostnameMapping[hostnameInfo.remoteHostName] = LocalDomainNameMapping(hostnameInfo, ip) + } } } @@ -125,13 +133,19 @@ class HttpWsExternalServiceHandler { return } - val ip: String = localAddressMapping[externalServiceInfo.remoteHostname] - ?: run { - val x = getNewIP() - lastIPAddress = x - localAddressMapping[externalServiceInfo.remoteHostname] = x - x - } +// val ip: String = localAddressMapping[externalServiceInfo.remoteHostname] +// ?: run { +// val x = getNewIP() +// lastIPAddress = x +// localAddressMapping[externalServiceInfo.remoteHostname] = x +// x +// } + + if (!hostnameMapping.containsKey(externalServiceInfo.remoteHostname)) { + return + } + + val ip: String = hostnameMapping[externalServiceInfo.remoteHostname]!!.localIP val registered = externalServices.filterValues { it.getRemoteHostName() == externalServiceInfo.remoteHostname && @@ -175,8 +189,12 @@ class HttpWsExternalServiceHandler { return externalServices.mapValues { it.value.getIP() } } - fun getLocalAddressMapping(): Map { - return localAddressMapping +// fun getLocalAddressMapping(): Map { +// return localAddressMapping +// } + + fun getLocalDomainNameMapping(): Map { + return hostnameMapping.mapValues { it.value.localIP } } /** diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt index b705829ae3..64583ec941 100755 --- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt @@ -8,6 +8,7 @@ import org.evomaster.client.java.controller.api.dto.TestResultsDto import org.evomaster.client.java.instrumentation.shared.ExternalServiceSharedUtils.getWMDefaultSignature import org.evomaster.core.Lazy import org.evomaster.core.logging.LoggingUtil +import org.evomaster.core.problem.externalservice.HostnameInfo import org.evomaster.core.problem.externalservice.httpws.service.HarvestActualHttpWsResponseHandler import org.evomaster.core.problem.externalservice.httpws.service.HttpWsExternalServiceHandler import org.evomaster.core.problem.externalservice.httpws.HttpExternalServiceInfo @@ -802,6 +803,13 @@ abstract class AbstractRestFitness : HttpWsFitness() where T : Individual */ infoDto.forEachIndexed { index, info -> + info.hostnameInfoDtos.forEach { hn -> + externalServiceHandler.addHostname(HostnameInfo( + hn.remoteHostname, + hn.resolved + )) + } + info.externalServices.forEach { es -> /* @@ -809,7 +817,7 @@ abstract class AbstractRestFitness : HttpWsFitness() where T : Individual */ /* - TODO: check, do we really want to start WireMock isntances right now after a fitness evaluation? + TODO: check, do we really want to start WireMock instances right now after a fitness evaluation? We need to make sure then, if we do this, that a call in instrumented SUT with (now) and without (previous fitness evaluation) WM instances would result in same behavior. @@ -841,9 +849,9 @@ abstract class AbstractRestFitness : HttpWsFitness() where T : Individual // TODO: Need to move under ApiWsFitness after the GraphQL and RPC support is completed if (index == 0) { actionDto.externalServiceMapping = externalServiceHandler.getExternalServiceMappings() - actionDto.localAddressMapping = externalServiceHandler.getLocalAddressMapping() + actionDto.localAddressMapping = externalServiceHandler.getLocalDomainNameMapping() actionDto.skippedExternalServices = externalServiceHandler.getSkippedExternalServices() } return actionDto } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt index 2039da7a60..f3f3cc6b23 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt @@ -9,6 +9,7 @@ import org.evomaster.core.EMConfig import org.evomaster.core.output.service.PartialOracles import org.evomaster.core.problem.enterprise.SampleType import org.evomaster.core.problem.externalservice.ExternalService +import org.evomaster.core.problem.externalservice.HostnameInfo import org.evomaster.core.problem.externalservice.httpws.HttpExternalServiceInfo import org.evomaster.core.problem.externalservice.httpws.service.HttpWsExternalServiceHandler import org.evomaster.core.problem.httpws.service.HttpWsSampler @@ -104,6 +105,8 @@ abstract class AbstractRestSampler : HttpWsSampler() { setupAuthentication(infoDto) initSqlInfo(infoDto) + initHostnameInfo(infoDto) + initExternalServiceInfo(infoDto) // TODO: temp @@ -318,6 +321,20 @@ abstract class AbstractRestSampler : HttpWsSampler() { } } + /** + * To collect external service info through SutInfoDto + */ + private fun initHostnameInfo(info: SutInfoDto) { + if (info.bootTimeInfoDto?.hostnameInfoDtos != null) { + info.bootTimeInfoDto.hostnameInfoDtos.forEach { + externalServiceHandler.addHostname(HostnameInfo( + it.remoteHostname, + it.resolved + )) + } + } + } + /** * To collect external service info through SutInfoDto */