You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by tm...@apache.org on 2019/08/10 15:08:11 UTC
[plc4x] 02/05: Implemented a Test for the Trigger Scraper.
This is an automated email from the ASF dual-hosted git repository.
tmitsch pushed a commit to branch feature/improve-scraper-tim
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 6c60ac3c1073f48c10de10ff54be89ee608d72c9
Author: julian <j....@pragmaticminds.de>
AuthorDate: Wed May 8 13:31:35 2019 +0200
Implemented a Test for the Trigger Scraper.
---
.../triggeredscraper/TriggeredScraperTask.java | 3 +-
.../triggerhandler/TriggerConfiguration.java | 1 +
.../triggerhandler/TriggerHandler.java | 28 +++--
.../triggeredscraper/TriggeredScraperImplTest.java | 116 +++++++++++++++++++++
.../scraper/src/test/resources/logback-test.xml | 5 +-
.../src/test/resources/mock-scraper-config.yml | 57 ++++++++++
6 files changed, 199 insertions(+), 11 deletions(-)
diff --git a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
index 1032c26..5cc7aaf 100644
--- a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
+++ b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
@@ -89,6 +89,7 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
@Override
//ToDo code-refactoring and improved testing --> PLC4X-90
public void run() {
+ LOGGER.trace("Check condition for task of job {} for connection {}", jobName, connectionAlias);
if(this.triggerHandler.checkTrigger()) {
// Does a single fetch only when trigger is valid
LOGGER.trace("Start new scrape of task of job {} for connection {}", jobName, connectionAlias);
@@ -233,7 +234,7 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
@Override
public double getPercentageFailed() {
- return (double)this.getScrapesSuccess()/this.getScrapesTotal() * 100.0;
+ return 100.0 - (double)this.getScrapesSuccess()/this.getScrapesTotal() * 100.0;
}
@Override
diff --git a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
index 8d7ba26..eb93cdc 100644
--- a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
+++ b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
@@ -76,6 +76,7 @@ public class TriggerConfiguration{
//test for valid field-connection string, on exception quit job and return message to user
try {
// TODO: PLC4X-106 - Make the Scraper not depend on S7 directly
+ // TODO: This should fetch the Field from the PLC Connection
this.plcField = S7Field.of(triggerVariable);
} catch (PlcInvalidFieldException e) {
logger.debug(e.getMessage(), e);
diff --git a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerHandler.java b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerHandler.java
index a2f45bb..29d5674 100644
--- a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerHandler.java
+++ b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerHandler.java
@@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit;
* holds the handler for the regarding trigger-scraper on rising-trigger edge
*/
public class TriggerHandler {
+
private static final Logger LOGGER = LoggerFactory.getLogger(TriggerHandler.class);
private static final String TRIGGER = "trigger";
@@ -45,7 +46,7 @@ public class TriggerHandler {
//used to enable trigger only on rising edge
private boolean lastTriggerState;
- public TriggerHandler(String triggerStrategy, TriggeredScrapeJobImpl triggeredScrapeJob,TriggeredScraperTask parentScraperTask) throws ScraperException {
+ public TriggerHandler(String triggerStrategy, TriggeredScrapeJobImpl triggeredScrapeJob, TriggeredScraperTask parentScraperTask) throws ScraperException {
this.triggerConfiguration = TriggerConfiguration.createConfiguration(triggerStrategy,triggeredScrapeJob);
this.parentScraperTask = parentScraperTask;
this.lastTriggerState = false;
@@ -73,7 +74,6 @@ public class TriggerHandler {
* @return true if rising-edge of trigger is detected, false otherwise
*/
private boolean checkS7TriggerVariable(){
-
CompletableFuture<PlcConnection> future = CompletableFuture.supplyAsync(() -> {
try {
return parentScraperTask.getDriverManager().getConnection(parentScraperTask.getConnectionString());
@@ -97,13 +97,23 @@ public class TriggerHandler {
boolean trigger = triggerConfiguration.evaluateTrigger(response.getObject(TRIGGER));
//only trigger scraping of data on rising edge of trigger
- if(trigger && !this.lastTriggerState){
- this.lastTriggerState = true;
- return true;
- }
- else{
- this.lastTriggerState = trigger;
- return false;
+ if(trigger == true){
+ if (this.lastTriggerState == false) {
+ this.lastTriggerState = true;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ // Trigger is false
+ if (this.lastTriggerState) {
+ // Triggered before, so RESET it
+ this.lastTriggerState = false;
+ return false;
+ } else {
+ // Simply return false
+ return false;
+ }
}
} catch (Exception e) {
diff --git a/plc4j/utils/scraper/src/test/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImplTest.java b/plc4j/utils/scraper/src/test/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImplTest.java
new file mode 100644
index 0000000..039b895
--- /dev/null
+++ b/plc4j/utils/scraper/src/test/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperImplTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.plc4x.java.scraper.triggeredscraper;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.base.messages.items.DefaultBooleanFieldItem;
+import org.apache.plc4x.java.base.messages.items.DefaultLongFieldItem;
+import org.apache.plc4x.java.mock.MockDevice;
+import org.apache.plc4x.java.mock.PlcMockConnection;
+import org.apache.plc4x.java.scraper.config.triggeredscraper.TriggeredScraperConfiguration;
+import org.apache.plc4x.java.scraper.exception.ScraperException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Random;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ *
+ * @author julian
+ * Created by julian on 2019-05-08
+ */
+public class TriggeredScraperImplTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(TriggeredScraperImplTest.class);
+ private PlcDriverManager driverManager;
+ private MockDevice mockDevice1;
+ private MockDevice mockDevice2;
+
+ @Before
+ public void setUp() throws Exception {
+ driverManager = new PlcDriverManager();
+ PlcMockConnection mock1Connection = ((PlcMockConnection) driverManager.getConnection("mock:1"));
+ PlcMockConnection mock2Connection = ((PlcMockConnection) driverManager.getConnection("mock:2"));
+
+ // Create Mocks
+ mockDevice1 = Mockito.mock(MockDevice.class);
+ mockDevice2 = Mockito.mock(MockDevice.class);
+ // Assign to Connections
+ mock1Connection.setDevice(mockDevice1);
+ mock2Connection.setDevice(mockDevice2);
+ }
+
+ /**
+ * Test is added because we assume some strange behavior.
+ */
+ @Test
+ public void scrapeMultipleTargets() throws ScraperException, IOException, InterruptedException {
+ // Prepare the Mocking
+ // Scrate Jobs 1 and 2
+ when(mockDevice1.read(eq("%DB810:DBB0:USINT"))).thenReturn(Pair.of(PlcResponseCode.OK, new DefaultLongFieldItem(1L)));
+ when(mockDevice2.read(eq("%DB810:DBB0:USINT"))).thenReturn(Pair.of(PlcResponseCode.OK, new DefaultLongFieldItem(2L)));
+ // Trigger Jobs
+ // Trigger var
+ Random rand = new Random();
+ when(mockDevice1.read(eq("%M0.3:BOOL"))).thenAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+ boolean trigger = rand.nextBoolean();
+ System.out.println(trigger);
+ return Pair.of(PlcResponseCode.OK, new DefaultBooleanFieldItem(trigger));
+ }
+ });
+ when(mockDevice2.read(eq("%M0.3:BOOL"))).thenAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+ boolean trigger = rand.nextBoolean();
+ System.out.println("\t\t" + trigger);
+ return Pair.of(PlcResponseCode.OK, new DefaultBooleanFieldItem(trigger));
+ }
+ });
+ // Read var
+ when(mockDevice1.read(eq("%DB810:DBW0:INT"))).thenReturn(Pair.of(PlcResponseCode.OK, new DefaultLongFieldItem(3L)));
+ when(mockDevice2.read(eq("%DB810:DBW0:INT"))).thenReturn(Pair.of(PlcResponseCode.OK, new DefaultLongFieldItem(4L)));
+
+ TriggeredScraperConfiguration configuration = TriggeredScraperConfiguration.fromFile("src/test/resources/mock-scraper-config.yml");
+ TriggeredScraperImpl scraper = new TriggeredScraperImpl((j, a, m) -> System.out.println(String.format("Results from %s/%s: %s", j, a, m)), driverManager, configuration.getJobs());
+
+ scraper.start();
+
+ Thread.sleep(2_000);
+
+ scraper.stop();
+ }
+}
\ No newline at end of file
diff --git a/plc4j/utils/scraper/src/test/resources/logback-test.xml b/plc4j/utils/scraper/src/test/resources/logback-test.xml
index c562020..3da2de8 100644
--- a/plc4j/utils/scraper/src/test/resources/logback-test.xml
+++ b/plc4j/utils/scraper/src/test/resources/logback-test.xml
@@ -29,8 +29,11 @@
</encoder>
</appender>
- <root level="INFO">
+ <root level="WARN">
<appender-ref ref="STDOUT"/>
</root>
+ <logger name="org.apache.plc4x.java.scraper.triggeredscraper" level="WARN" additivity="false">
+ <appender-ref ref="STDOUT"/>
+ </logger>
</configuration>
\ No newline at end of file
diff --git a/plc4j/utils/scraper/src/test/resources/mock-scraper-config.yml b/plc4j/utils/scraper/src/test/resources/mock-scraper-config.yml
new file mode 100644
index 0000000..face235
--- /dev/null
+++ b/plc4j/utils/scraper/src/test/resources/mock-scraper-config.yml
@@ -0,0 +1,57 @@
+# ----------------------------------------------------------------------------
+# 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.
+# ----------------------------------------------------------------------------
+---
+sources:
+ MOCK_1: mock:1
+ MOCK_2: mock:2
+
+jobs:
+ - name: scheduled-demo-job1
+ triggerConfig: (SCHEDULED,100)
+ sources:
+ - MOCK_1
+ - MOCK_2
+ fields:
+ test1: '%DB810:DBB0:USINT'
+
+ - name: scheduled-demo-job2
+ triggerConfig: (SCHEDULED,100)
+ sources:
+ - MOCK_1
+ - MOCK_2
+ fields:
+ test1: '%DB810:DBB0:USINT'
+
+
+ - name: triggered-demo-job1
+ triggerConfig: (S7_TRIGGER_VAR,10,(%M0.3:BOOL)==(true))
+ sources:
+ - MOCK_1
+ - MOCK_2
+ fields:
+ test1: '%DB810:DBW0:INT'
+
+
+ - name: triggered-demo-job2
+ triggerConfig: (S7_TRIGGER_VAR,10,(%M0.7:BOOL)==(true))
+ sources:
+ - MOCK_1
+ - MOCK_2
+ fields:
+ test1: '%DB810:DBW0:INT'
\ No newline at end of file