diff --git a/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/assertor/VariableExpressParser.java b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/assertor/VariableExpressParser.java new file mode 100644 index 0000000000..e509a7bfce --- /dev/null +++ b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/assertor/VariableExpressParser.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.e2e.assertor; + +import org.apache.skywalking.e2e.assertor.exception.VariableNotFoundException; + +import java.util.List; +import java.util.function.Function; +import java.util.regex.Pattern; + +import static java.util.Objects.isNull; + +/** + * @author zhangwei + */ +public class VariableExpressParser { + + + public static T parse(String express, List actual, Function getFiled) { + express = express.trim(); + if (!(express.startsWith("${") && express.endsWith("}"))) { + return null; + } + + express = express.substring(2, express.length() - 1); + + int startIndexOfIndex = express.lastIndexOf("["); + String regex = express.substring(0, startIndexOfIndex); + int endIndexOfIndex = express.indexOf("]", startIndexOfIndex); + int expectedIndex = Integer.parseInt(express.substring(startIndexOfIndex + 1, endIndexOfIndex)); + int mappingIndex = 0; + + T mapping = null; + for (T t : actual) { + if (Pattern.matches(regex, getFiled.apply(t))) { + if (mappingIndex++ == expectedIndex) { + mapping = t; + break; + } + } + } + + if (isNull(mapping)) { + throw new VariableNotFoundException(express); + } + return mapping; + } +} diff --git a/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/assertor/exception/VariableNotFoundException.java b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/assertor/exception/VariableNotFoundException.java new file mode 100644 index 0000000000..a90e4be8cc --- /dev/null +++ b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/assertor/exception/VariableNotFoundException.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.e2e.assertor.exception; + +import org.apache.skywalking.e2e.exception.AssertFailedException; + +/** + * @author zhangwei + */ +public class VariableNotFoundException extends AssertFailedException { + + private static final long serialVersionUID = 1337142072507388456L; + + private final String express; + + public VariableNotFoundException(String express) { + this.express = express; + } + + @Override + public String getCauseMessage() { + return String.format("VariableNotFoundException\nexpected: %s\nactual: %s\n", express, "NOT FOUND"); + } +} diff --git a/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/exception/AssertFailedException.java b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/exception/AssertFailedException.java new file mode 100644 index 0000000000..a1e0cf3b7f --- /dev/null +++ b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/exception/AssertFailedException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.e2e.exception; +/** + * Created by xin on 2017/7/15. + */ +public abstract class AssertFailedException extends RuntimeException { + + private static final long serialVersionUID = 8870675340514007954L; + + protected AssertFailedException(String message) { + super(message); + } + + protected AssertFailedException(){ + } + + public abstract String getCauseMessage(); +} diff --git a/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java index 9d7ec35e43..bc143b29ce 100644 --- a/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java +++ b/test/e2e/e2e-base/src/main/java/org/apache/skywalking/e2e/topo/TopoMatcher.java @@ -18,11 +18,12 @@ package org.apache.skywalking.e2e.topo; +import org.apache.skywalking.e2e.assertor.VariableExpressParser; import org.apache.skywalking.e2e.verification.AbstractMatcher; import java.util.List; -import java.util.Objects; +import static java.util.Objects.nonNull; import static org.assertj.core.api.Assertions.fail; /** @@ -37,11 +38,12 @@ public class TopoMatcher extends AbstractMatcher { @Override public void verify(final TopoData topoData) { - if (Objects.nonNull(getNodes())) { + if (nonNull(getNodes())) { verifyNodes(topoData); } - if (Objects.nonNull(getCalls())) { + if (nonNull(getCalls())) { + convertNodeId(getCalls(), topoData.getNodes()); verifyCalls(topoData); } } @@ -101,4 +103,26 @@ public class TopoMatcher extends AbstractMatcher { ", calls=" + calls + '}'; } + + + private static void convertNodeId(List callMatchers, List nodes) { + for (CallMatcher callMatcher : callMatchers) { + Node sourceNode = VariableExpressParser.parse(callMatcher.getSource(), nodes, Node::getName); + Node targetNode = VariableExpressParser.parse(callMatcher.getTarget(), nodes, Node::getName); + + boolean convert = false; + if (nonNull(sourceNode)) { + callMatcher.setSource(sourceNode.getId()); + convert = true; + } + if (nonNull(targetNode)) { + callMatcher.setTarget(targetNode.getId()); + convert = true; + } + + if (convert) { + callMatcher.setId(String.join("_", callMatcher.getSource(), callMatcher.getTarget())); + } + } + } } diff --git a/test/e2e/e2e-base/src/test/java/org/apache/skywalking/e2e/TestTopoMatcher.java b/test/e2e/e2e-base/src/test/java/org/apache/skywalking/e2e/TestTopoMatcher.java new file mode 100644 index 0000000000..13885f075b --- /dev/null +++ b/test/e2e/e2e-base/src/test/java/org/apache/skywalking/e2e/TestTopoMatcher.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.e2e; + +import org.apache.skywalking.e2e.assertor.exception.VariableNotFoundException; +import org.apache.skywalking.e2e.topo.Call; +import org.apache.skywalking.e2e.topo.Node; +import org.apache.skywalking.e2e.topo.TopoData; +import org.apache.skywalking.e2e.topo.TopoMatcher; +import org.junit.Before; +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; +import org.yaml.snakeyaml.Yaml; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zhangwei + */ +public class TestTopoMatcher { + + private TopoMatcher topoMatcher; + + @Before + public void setUp() throws IOException { + try (InputStream expectedInputStream = new ClassPathResource("topo.yml").getInputStream()) { + topoMatcher = new Yaml().loadAs(expectedInputStream, TopoMatcher.class); + } + } + + @Test + public void shouldSuccess() { + final List nodes = new ArrayList<>(); + nodes.add(new Node().setId("1").setName("User").setType("USER").setIsReal("false")); + nodes.add(new Node().setId("2").setName("projectB-pid:27960@skywalking-server-0001").setType("Tomcat").setIsReal("true")); + nodes.add(new Node().setId("3").setName("projectB-pid:27961@skywalking-server-0001").setType("Tomcat").setIsReal("true")); + + + final List calls = new ArrayList<>(); + calls.add(new Call().setId("1_2").setSource("1").setTarget("2")); + calls.add(new Call().setId("1_3").setSource("1").setTarget("3")); + + final TopoData topoData = new TopoData().setNodes(nodes).setCalls(calls); + + topoMatcher.verify(topoData); + } + + @Test(expected = VariableNotFoundException.class) + public void shouldVariableNotFound() { + final List nodes = new ArrayList<>(); + nodes.add(new Node().setId("1").setName("User").setType("USER").setIsReal("false")); + nodes.add(new Node().setId("2").setName("projectA-pid:27960@skywalking-server-0001").setType("Tomcat").setIsReal("true")); + nodes.add(new Node().setId("3").setName("projectB-pid:27961@skywalking-server-0001").setType("Tomcat").setIsReal("true")); + + + final List calls = new ArrayList<>(); + calls.add(new Call().setId("1_2").setSource("1").setTarget("2")); + calls.add(new Call().setId("1_3").setSource("1").setTarget("3")); + + final TopoData topoData = new TopoData().setNodes(nodes).setCalls(calls); + + topoMatcher.verify(topoData); + } +} diff --git a/test/e2e/e2e-base/src/test/resources/topo.yml b/test/e2e/e2e-base/src/test/resources/topo.yml new file mode 100644 index 0000000000..1ae5b014df --- /dev/null +++ b/test/e2e/e2e-base/src/test/resources/topo.yml @@ -0,0 +1,39 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# 1 health-check by docker-maven-plugin +# 1 drop table if exists, because we have `ddl-auto: create-drop` +# 1 drop sequence +# 1 create sequence +# 1 create table statement + +nodes: + - id: not null + name: User + type: USER + - id: not null + name: not null + type: Tomcat + - id: not null + name: not null + type: Tomcat +calls: + - id: not null + source: ${User[0]} + target: ${projectB-pid:(.*)@skywalking-server-0001[0]} + - id: not null + source: ${User[0]} + target: ${projectB-pid:(.*)@skywalking-server-0001[1]} \ No newline at end of file diff --git a/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml b/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml index 8f58605cf4..2e984d33c3 100644 --- a/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml +++ b/test/e2e/e2e-cluster/test-runner/src/test/resources/expected-data/org.apache.skywalking.e2e.ClusterVerificationITCase.topo.yml @@ -32,14 +32,14 @@ nodes: type: Unknown calls: - id: not null - source: not null - target: not null + source: ${User[0]} + target: ${consumer[0]} - id: not null - source: not null - target: not null + source: ${127.0.0.1:9099[0]} + target: ${provider[0]} - id: not null - source: not null - target: not null + source: ${consumer[0]} + target: ${127.0.0.1:9099[0]} - id: not null - source: not null - target: not null + source: ${provider[0]} + target: ${localhost:-1[0]}