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