details:   https://code.openbravo.com/erp/devel/pi/rev/2df0dc2f8b08
changeset: 35235:2df0dc2f8b08
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Thu Dec 13 12:07:51 2018 +0100
summary:   related with issue 39755: prevent time based thread syncrhonization 
in tests

  Time based synchronization is error-prone and can cause false positives.

  Synchronizing events now with CountDownLatch.

diffstat:

 src-test/src/org/openbravo/test/dal/DalLockingTest.java |  66 ++++++++++++----
 1 files changed, 48 insertions(+), 18 deletions(-)

diffs (139 lines):

diff -r 29bb5d02e0fe -r 2df0dc2f8b08 
src-test/src/org/openbravo/test/dal/DalLockingTest.java
--- a/src-test/src/org/openbravo/test/dal/DalLockingTest.java   Thu Dec 13 
00:01:44 2018 +0530
+++ b/src-test/src/org/openbravo/test/dal/DalLockingTest.java   Thu Dec 13 
12:07:51 2018 +0100
@@ -29,6 +29,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -67,7 +68,7 @@
 
   @BeforeClass
   public static void createTestEnvironment() {
-    OBContext.setAdminMode();
+    OBContext.setAdminMode(true);
     try {
       AlertRule newAlertRule = OBProvider.getInstance().get(AlertRule.class);
       newAlertRule.setName(DalLockingTest.class.getName() + " - Testing Alert 
Rule");
@@ -101,10 +102,10 @@
 
   @Test
   public void objectShouldBeLockedInDB() throws InterruptedException, 
ExecutionException {
+    CountDownLatch latch = new CountDownLatch(1);
     List<Callable<Void>> threads = Arrays.asList(
-        //
-        getDalCallable(this::acquireLock, "T1", 0, 200),
-        getDalCallable(this::acquireLock, "T2", 100, 0));
+        getDalCallable(() -> acquireLock(latch), "T1", 200), //
+        getDalCallable(this::acquireLock, "T2", latch));
 
     executeAndGetResults(threads);
     assertThat(
@@ -115,14 +116,15 @@
   @Test
   public void lockedObjectShouldAllowChildrenCreation() throws 
InterruptedException,
       ExecutionException {
+    CountDownLatch latch = new CountDownLatch(1);
     List<Callable<Void>> threads = Arrays.asList( //
-        getDalCallable(this::acquireLock, "T1", 0, 200), //
+        getDalCallable(() -> acquireLock(latch), "T1", 200), //
         getDalCallable(() -> {
           AlertRecipient recipient = 
OBProvider.getInstance().get(AlertRecipient.class);
           recipient.setRole(OBContext.getOBContext().getRole());
           recipient.setAlertRule(getTestingAlertRule());
           OBDal.getInstance().save(recipient);
-        }, "T2", 100, 0));
+        }, "T2", latch));
 
     executeAndGetResults(threads);
     assertThat(
@@ -134,21 +136,21 @@
   public void lockedInstanceGetsRefreshedFromDB() throws InterruptedException, 
ExecutionException {
     StringBuilder originalName = new StringBuilder();
     StringBuilder lockedName = new StringBuilder();
+    CountDownLatch gotRule = new CountDownLatch(1);
+    CountDownLatch ruleModified = new CountDownLatch(1);
     List<Callable<Void>> threads = Arrays.asList( //
         getDalCallable(() -> {
           AlertRule ar = getTestingAlertRule();
           originalName.append(ar.getName());
-
-          try {
-            TimeUnit.MILLISECONDS.sleep(200);
-          } catch (InterruptedException e) {
-          }
-
+          gotRule.countDown();
+          waitUnitl(ruleModified);
           
lockedName.append(OBDal.getInstance().getObjectLockForNoKeyUpdate(ar).getName());
-        }, "T1", 0, 0), //
+        }, "T1", 0), //
         getDalCallable(() -> {
           getTestingAlertRule().setName("Modified");
-        }, "T2", 100, 0));
+          OBDal.getInstance().commitAndClose();
+          ruleModified.countDown();
+        }, "T2", gotRule));
 
     executeAndGetResults(threads);
 
@@ -176,12 +178,21 @@
     }
   }
 
-  private Callable<Void> getDalCallable(Runnable r, String name, long 
waitBefore, long waitAfter) {
+  private Callable<Void> getDalCallable(Runnable r, String name, 
CountDownLatch waitFor) {
+    return getDalCallable(r, name, waitFor, 0);
+  }
+
+  private Callable<Void> getDalCallable(Runnable r, String name, long 
waitAfter) {
+    return getDalCallable(r, name, null, waitAfter);
+  }
+
+  private Callable<Void> getDalCallable(Runnable r, String name, 
CountDownLatch waitEvent,
+      long waitAfter) {
     return () -> {
       boolean errorOccurred = false;
       try {
-        OBContext.setAdminMode();
-        TimeUnit.MILLISECONDS.sleep(waitBefore);
+        OBContext.setAdminMode(true);
+        waitUnitl(waitEvent);
         r.run();
         TimeUnit.MILLISECONDS.sleep(waitAfter);
         return null;
@@ -213,11 +224,30 @@
   }
 
   private AlertRule acquireLock() {
-    return OBDal.getInstance().getObjectLockForNoKeyUpdate(
+    return acquireLock(null);
+  }
+
+  private AlertRule acquireLock(CountDownLatch latch) {
+    AlertRule lockedRule = OBDal.getInstance().getObjectLockForNoKeyUpdate(
         OBDal.getInstance().getProxy(AlertRule.class, testingRuleId));
+    if (latch != null) {
+      latch.countDown();
+    }
+    return lockedRule;
   }
 
   private static AlertRule getTestingAlertRule() {
     return OBDal.getInstance().get(AlertRule.class, testingRuleId);
   }
+
+  private void waitUnitl(CountDownLatch event) {
+    if (event == null) {
+      return;
+    }
+    try {
+      event.await(10L, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      throw new OBException(e);
+    }
+  }
 }


_______________________________________________
Openbravo-commits mailing list
Openbravo-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbravo-commits

Reply via email to