From 6537b5b88cac5b2f31d014687dbef6acfdad623a Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 2 Jun 2020 01:36:17 +0200 Subject: [PATCH] FsMsgQueue complete --- .../test/templateAliceBob/TestAlice.java | 18 +- .../test/templateAliceBob/TestBob.java | 22 +- .../test/utils/fsmsgqueue/FsMsgQueue.java | 224 +++++++++++++----- .../fsmsgqueue/test/readwrite/TestMain.java | 129 ++++++---- 4 files changed, 268 insertions(+), 125 deletions(-) diff --git a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java index e278ac4..6e8b0e3 100644 --- a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java +++ b/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestAlice.java @@ -1,5 +1,7 @@ package foundation.pEp.jniadapter.test.templateAliceBob; + import static foundation.pEp.jniadapter.test.framework.TestLogger.*; + import foundation.pEp.jniadapter.test.framework.*; import foundation.pEp.jniadapter.test.utils.*; @@ -8,23 +10,25 @@ class TestAlice { TestSuite.setVerbose(true); TestSuite.setTestColor(TestUtils.TermColor.GREEN); - new TestUnit("Test Alice",new AdapterBaseTestContext() , ctx -> { - // do stuff using the context - // Test FAILS on unhandled exception, otherwise SUCCESS - + new TestUnit("Alice tx msg", new AdapterBaseTestContext(), ctx -> { ctx.alice = ctx.engine.myself(ctx.alice); - if(ctx.alice.fpr == null) { + if (ctx.alice.fpr == null) { throw new RuntimeException(); } - for(int i=0; i < 1000; i++ ) { - log("Alice is waiting..."); + //send message + }).add(); + + new TestUnit("Alice rx msg", new AdapterBaseTestContext(), ctx -> { + for (int i = 0; i < 1000; i++) { + log("Alice is waiting for msg..."); TestUtils.sleep(1000); } }).add(); + TestSuite.run(); } } diff --git a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java b/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java index 8543112..f786af4 100644 --- a/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java +++ b/test/java/foundation/pEp/jniadapter/test/templateAliceBob/TestBob.java @@ -1,5 +1,7 @@ package foundation.pEp.jniadapter.test.templateAliceBob; + import static foundation.pEp.jniadapter.test.framework.TestLogger.*; + import foundation.pEp.jniadapter.test.framework.*; import foundation.pEp.jniadapter.test.utils.*; @@ -8,23 +10,25 @@ class TestBob { TestSuite.setVerbose(true); TestSuite.setTestColor(TestUtils.TermColor.YELLOW); - new TestUnit("Test Bob",new AdapterBaseTestContext() , ctx -> { - // do stuff using the context - // Test FAILS on unhandled exception, otherwise SUCCESS + new TestUnit("Bob rx msg", new AdapterBaseTestContext(), ctx -> { + for (int i = 0; i < 1000; i++) { + log("Bob is waiting for msg..."); + TestUtils.sleep(1000); + } + + }).add(); + new TestUnit("Bob tx msg", new AdapterBaseTestContext(), ctx -> { ctx.bob = ctx.engine.myself(ctx.bob); - if(ctx.bob.fpr == null) { + if (ctx.bob.fpr == null) { throw new RuntimeException(); } - for(int i=0; i < 1000; i++ ) { - log("Bob is waiting..."); - TestUtils.sleep(1000); - } - + //send message }).add(); + TestSuite.run(); } } diff --git a/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/FsMsgQueue.java b/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/FsMsgQueue.java index af16ce1..e4f1de9 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/FsMsgQueue.java +++ b/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/FsMsgQueue.java @@ -3,23 +3,29 @@ package foundation.pEp.jniadapter.test.utils.fsmsgqueue; import static foundation.pEp.jniadapter.test.framework.TestLogger.*; import foundation.pEp.jniadapter.test.framework.*; +import foundation.pEp.jniadapter.test.framework.TestUtils.*; import foundation.pEp.jniadapter.test.utils.*; + import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Parameter; +import java.math.BigInteger; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; import javafx.util.Pair; public class FsMsgQueue implements Queue { File qDir; + Charset fileEncoding; public FsMsgQueue(String qDirPath) throws RuntimeException { qDir = new File(qDirPath); @@ -33,6 +39,9 @@ public class FsMsgQueue implements Queue { // Dir already exists } // Dir now definitely exists +// log("Available Charsets: " + getAvailableCharsetNames()); + fileEncoding = Charset.forName("UTF-8"); + log("Using charset: " + fileEncoding.name()); } @Override @@ -46,18 +55,51 @@ public class FsMsgQueue implements Queue { } @Override - public boolean add(String msg) { + public boolean add(String msg) throws NullPointerException, IllegalStateException { boolean ret = true; - String filename = UUID.randomUUID().toString() + ".msg"; - String path = qDir + "/" + filename; - try { - Files.write(Paths.get(path), msg.getBytes()); - } catch (IOException e) { - log(e.toString()); + String readBack = null; + if (msg != null) { + String filename = getNewFilename(); + String path = qDir + "/" + filename; + // check file not existing yet. + log("Adding msg file:" + filename); + File file = new File(path); + + if(!file.exists()) { + try { + writeFile(file.toPath(), msg, fileEncoding); + readBack = readFile(Paths.get(path), fileEncoding); + } catch (IOException e) { + log(e.toString()); + throw new IllegalStateException(); + } + if (!readBack.equals(msg)) { + throw new IllegalStateException("Readback failed:\nwrite:\"" + msg + "\"\nread :\"" + readBack + "\""); + } + } else { + throw new IllegalStateException("Cant create new msg file, already exists:" + path); + } + } else { + throw new NullPointerException(); } return ret; } + + private String getNewFilename() { + String ret = ""; + List msgFiles = dotMsgFilesSorted(qDir, true); + int newNumber = 0; + if(msgFiles.size() > 0) { + File latest = msgFiles.get(msgFiles.size() - 1); + newNumber = Integer.parseInt(latest.getName().replace(".msg", "")) + 1; + } + ret = TestUtils.padOrClipString(String.valueOf(newNumber),"0",12,Alignment.Right,""); + ret += ".msg"; + + return ret; + } + @Override public boolean offer(String msg) { boolean ret = true; @@ -69,29 +111,26 @@ public class FsMsgQueue implements Queue { return ret; } + private File getOldestMsgFilename() { + File ret = null; + List msgFiles = dotMsgFilesSorted(qDir, false); + if(msgFiles.size() > 0) { + File oldest = msgFiles.get(msgFiles.size() - 1); + ret = oldest; + } + return ret; + } + private Pair get() throws Exception { Pair ret = null; - ArrayList files = listFilesByMtime(qDir); - File oldestFile = null; - if (files == null || (files.size() <= 0)) { - throw new NoSuchElementException("Dir empty: " + qDir); + File oldestFile = getOldestMsgFilename(); + log("reading file:" + oldestFile.getName()); + if (oldestFile == null) { + throw new NoSuchElementException("MNo .msg file in dir: " + qDir); } else { - oldestFile = files.get(0); - if(oldestFile != null) { - String fContent = null; - try { - fContent = readFile(oldestFile.toPath(), Charset.defaultCharset()); - } catch (Exception e) { - throw new Exception("Error reading file: " + oldestFile.getAbsolutePath()); - } - if(fContent != null) { - ret = new Pair<>(oldestFile,fContent); - } else { - throw new Exception("Error reading file: " + oldestFile.getAbsolutePath()); - } - } else { - throw new NoSuchElementException("Dir empty: " + qDir); - } + String fContent = null; + fContent = readFile(oldestFile.toPath(), fileEncoding); + ret = new Pair<>(oldestFile, fContent); } return ret; } @@ -108,10 +147,10 @@ public class FsMsgQueue implements Queue { } // Successful read // remove now - if (pair != null ) { + if (pair != null) { file = pair.getKey(); ret = pair.getValue(); - if(file != null && ret != null) { + if (file != null && ret != null) { file.delete(); if (file.exists()) { throw new RuntimeException("Cant remove msg from queue: " + file.getAbsolutePath()); @@ -138,11 +177,11 @@ public class FsMsgQueue implements Queue { String ret = null; Pair pair = null; try { - pair = get(); + pair = get(); } catch (Exception e) { throw new NoSuchElementException(e.toString()); } - if(pair != null) { + if (pair != null) { ret = pair.getValue(); } else { throw new NoSuchElementException("Unknown Error"); @@ -162,80 +201,111 @@ public class FsMsgQueue implements Queue { @Override - public boolean addAll(Collection c) { - return false; + public void clear() { + deleteContentsRecursively(qDir); } - + // Not implemented @Override - public void clear() { - + public boolean addAll(Collection c) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public boolean contains(Object o) { - return false; + public boolean contains(Object o) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public Iterator iterator() { - return null; + public Iterator iterator() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public Object[] toArray() { - return new Object[0]; + public Object[] toArray() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public T[] toArray(T[] a) { - return null; + public T[] toArray(T[] a) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public boolean remove(Object o) { - return false; + public boolean remove(Object o) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public boolean containsAll(Collection c) { - return false; + public boolean containsAll(Collection c) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public boolean removeAll(Collection c) { - return false; + public boolean removeAll(Collection c) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } // Not implemented @Override - public boolean retainAll(Collection c) { - return false; + public boolean retainAll(Collection c) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); } //Math Utils - private int clip(int val, int min, int max) { + public static int clip(int val, int min, int max) { return Math.max(min, Math.min(max, val)); } - private long clip(long val, long min, long max) { + public static long clip(long val, long min, long max) { return Math.max(min, Math.min(max, val)); } // File Utils + // Possibly returns an empty List + private static List dotMsgFilesSorted(File dir, boolean ascending) { + List ret = new ArrayList<>(); + File[] listOfFiles = dir.listFiles(); + if (listOfFiles != null) { + Collections.addAll(ret, listOfFiles); + if (ret.size() > 0) { + ret = filterbyFilename(ret, ".*\\.msg$"); + Collections.sort(ret, (o1, o2) -> { + long ret1 = 0; + int f1 = Integer.parseInt(o1.getName().replace(".msg", "")); + int f2 = Integer.parseInt(o2.getName().replace(".msg", "")); + ret1 = f1 - f2; + if (!ascending) { + ret1 = ret1 * -1; + } + return (int) clip(ret1, -1, 1); + }); + } + } + return ret; + } + + // possibly returns an empty list + private static List filterbyFilename(List files, String regex) { + List ret = null; + Predicate dotMsg = file -> file.getName().matches(regex); + ret = files.stream().filter(dotMsg).collect(Collectors.toList()); + return ret; + } + // Possibly returns an empty ArrayList - private ArrayList listFilesByMtime(File dir) { - ArrayList ret = new ArrayList<>(); + private static List listFilesByMtime(File dir) { + List ret = new ArrayList<>(); File[] listOfFiles = dir.listFiles(); if (listOfFiles != null) { Collections.addAll(ret, listOfFiles); @@ -245,8 +315,8 @@ public class FsMsgQueue implements Queue { } // null in null out - private ArrayList sortFilesByMtime(ArrayList files) { - ArrayList ret = null; + private static List sortFilesByMtime(List files) { + List ret = null; if (files != null) { ret = new ArrayList(files); Collections.sort(ret, (o1, o2) -> { @@ -258,11 +328,45 @@ public class FsMsgQueue implements Queue { return ret; } - static String readFile(Path path, Charset encoding) throws IOException { + public static String readFile(Path path, Charset decoding) throws IOException { + String ret = null; byte[] encoded = Files.readAllBytes(path); - return new String(encoded, encoding); + ret = new String(encoded, decoding); + if (ret == null) { + throw new IOException("Error reading file: " + path); + } + return ret; + } + + public static void writeFile(Path path, String msg, Charset encoding) throws IOException { + Files.write(path, msg.getBytes(encoding)); } + public static boolean deleteRecursively(File dir) { + deleteContentsRecursively(dir); + log("deleting: " + dir.getAbsolutePath()); + return dir.delete(); + } + + public static boolean deleteContentsRecursively(File dir) { + boolean ret = false; + File[] allContents = dir.listFiles(); + if (allContents != null) { + for (File file : allContents) { + ret = deleteRecursively(file); + } + } + return ret; + } + + private static List getAvailableCharsetNames() { + List ret = new ArrayList<>(); + for (String key : Charset.availableCharsets().keySet()) { + Charset val = Charset.forName(key); + ret.add(val.name()); + } + return ret; + } } diff --git a/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/test/readwrite/TestMain.java b/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/test/readwrite/TestMain.java index ce5273e..73d30bb 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/test/readwrite/TestMain.java +++ b/test/java/foundation/pEp/jniadapter/test/utils/fsmsgqueue/test/readwrite/TestMain.java @@ -1,6 +1,7 @@ package foundation.pEp.jniadapter.test.utils.fsmsgqueue.test.readwrite; import static foundation.pEp.jniadapter.test.framework.TestLogger.*; +import static foundation.pEp.jniadapter.test.utils.fsmsgqueue.FsMsgQueue.*; import foundation.pEp.jniadapter.test.framework.*; import foundation.pEp.jniadapter.test.utils.*; @@ -8,11 +9,12 @@ import foundation.pEp.jniadapter.test.utils.fsmsgqueue.*; import java.io.File; import java.util.ArrayList; +import java.util.NoSuchElementException; class FsMsgQueueTestContext extends AbstractTestContext { String qDirPath = "../resources/fsmsgqueue-test/q1"; - int msgCount = 4; + int msgCount = 10; ArrayList messages; FsMsgQueue queue; @@ -26,7 +28,7 @@ class FsMsgQueueTestContext extends AbstractTestContext { public void deleteQDir() { File qDir = new File(qDirPath); if (qDir.exists()) { - log("Deleting Queue Dir: " + qDirPath); + log("Deleting queue dir: " + qDirPath); deleteRecursively(qDir); if (qDir.exists()) throw new RuntimeException("Cant delete Dir:" + qDirPath); } @@ -37,24 +39,13 @@ class FsMsgQueueTestContext extends AbstractTestContext { ArrayList messages = new ArrayList<>(); for (int i = 0; i < count; i++) { String msg = "TestMessage " + i; - msg += "\nLine 2 of " + msg; + // msg += "\nLine 2 of " + msg; messages.add(msg); log("Creating msg: " + msg); } return messages; } - // FileUtils - - boolean deleteRecursively(File dir) { - File[] allContents = dir.listFiles(); - if (allContents != null) { - for (File file : allContents) { - deleteRecursively(file); - } - } - return dir.delete(); - } } class TestMain { @@ -63,70 +54,110 @@ class TestMain { FsMsgQueueTestContext testCtx = new FsMsgQueueTestContext(); new TestUnit("Constructor", testCtx, ctx -> { + log("Creating queue obj on dir:" + ctx.qDirPath); ctx.queue = new FsMsgQueue(ctx.qDirPath); }).add(); - new TestUnit("Add", testCtx, ctx -> { + TestUnit isEmpty = new TestUnit("isEmpty", testCtx, ctx -> { + log("Checking queue is empty"); + assert ctx.queue.isEmpty(); + }).add(); + + TestUnit size0 = new TestUnit("Size == 0", testCtx, ctx -> { + log("Checking queue size == 0"); + assert ctx.queue.size() == 0; + }).add(); + + new TestUnit("write msg[0]", testCtx, ctx -> { + String msg = ctx.messages.get(0); + log("adding msg[0]:" + msg); + ctx.queue.add(msg); + }).add(); + + TestUnit notEmpty = new TestUnit("Not empty", testCtx, ctx -> { + log("Checking queue not empty"); + assert !ctx.queue.isEmpty(); + }).add(); + + new TestUnit("Size == 1", testCtx, ctx -> { + log("Checking queue size == 1"); + assert ctx.queue.size() == 1; + }).add(); + + + new TestUnit("read equals write (element)", testCtx, ctx -> { + String msg = ctx.queue.element(); + log("Read:" + msg); + assert msg.equals(ctx.messages.get(0)); + }).add(); + + new TestUnit("read equals write (remove)", testCtx, ctx -> { + String msg = ctx.queue.remove(); + log("Read:" + msg); + assert msg.equals(ctx.messages.get(0)); + }).add(); + + isEmpty.add(); + size0.add(); + + TestUnit addAllMsgs = new TestUnit("Add " + testCtx.msgCount + " msgs", testCtx, ctx -> { for (String msg : ctx.messages) { log("Adding msg:" + msg); ctx.queue.add(msg); } }).add(); - new TestUnit("Element", testCtx, ctx -> { - String msg = ctx.queue.element(); - log("Element: " + msg); - }).add(); - - new TestUnit("Size", testCtx, ctx -> { + TestUnit sizeFull = new TestUnit("Size == " + testCtx.msgCount, testCtx, ctx -> { int size = ctx.queue.size(); log("Size: " + size); assert size == ctx.msgCount; }).add(); - new TestUnit("isEmpty", testCtx, ctx -> { - boolean isEmpty = ctx.queue.isEmpty(); - log("isEmpty: " + isEmpty); - assert !isEmpty; - }).add(); + notEmpty.add(); - new TestUnit("remove", testCtx, ctx -> { + new TestUnit("read all equals write", testCtx, ctx -> { + int msgIndex = 0; while (!ctx.queue.isEmpty()) { String msg = ctx.queue.remove(); - log("remove: " + msg); + String expected = ctx.messages.get(msgIndex); + log("Expected:" + expected); + log("Returned:" + msg); + assert msg.equals(expected); + msgIndex++; } }).add(); - new TestUnit("Size 0", testCtx, ctx -> { - int size = ctx.queue.size(); - log("Size: " + size); - assert size == 0; - }).add(); + addAllMsgs.add(); + notEmpty.add(); + sizeFull.add(); - new TestUnit("isEmpty true", testCtx, ctx -> { - boolean isEmpty = ctx.queue.isEmpty(); - log("isEmpty: " + isEmpty); - assert isEmpty; + TestUnit clear = new TestUnit("Clear", testCtx, ctx -> { + ctx.queue.clear(); }).add(); - new TestUnit("Element on empty", testCtx, ctx -> { + isEmpty.add(); + size0.add(); + + new TestUnit("Empty queue: element()", testCtx, ctx -> { try { - String msg = ctx.queue.element(); - log("Element: " + msg); - } catch (Exception e) { - return; + ctx.queue.element(); + } catch (NoSuchElementException e) { } - assert false; }).add(); - new TestUnit("Remove on empty", testCtx, ctx -> { + new TestUnit("Empty queue: peek()", testCtx, ctx -> { + assert ctx.queue.peek() == null; + }).add(); + + new TestUnit("Empty queue: remove()", testCtx, ctx -> { try { - String msg = ctx.queue.remove(); - log("Element: " + msg); - } catch (Exception e) { - return; + ctx.queue.remove(); + } catch (NoSuchElementException e) { } - assert false; + }).add(); + + new TestUnit("Empty queue: poll()", testCtx, ctx -> { + assert ctx.queue.poll() == null; }).add();