Browse Source

JNI-160: add Test (extend JNI-135 test)

JNI-160
heck 11 months ago
parent
commit
495ab5a085
1 changed files with 127 additions and 49 deletions
  1. +127
    -49
      test/java/foundation/pEp/jniadapter/test/jni135/TestAlice.java

+ 127
- 49
test/java/foundation/pEp/jniadapter/test/jni135/TestAlice.java View File

@ -1,78 +1,156 @@
package foundation.pEp.jniadapter.test.jni135;
import foundation.pEp.jniadapter.Blob;
import foundation.pEp.jniadapter.Engine;
import foundation.pEp.jniadapter.Message;
import foundation.pEp.jniadapter.decrypt_message_Return;
import foundation.pEp.jniadapter.test.utils.CTXBase;
import foundation.pEp.jniadapter.*;
import foundation.pEp.jniadapter.test.utils.AdapterTestUtils;
import foundation.pEp.jniadapter.test.utils.model.Role;
import foundation.pEp.jniadapter.test.utils.model.TestModel;
import foundation.pEp.jniadapter.test.utils.model.TestNode;
import foundation.pEp.jniadapter.test.utils.model.pEpTestIdentity;
import foundation.pEp.pitytest.AbstractTestContext;
import foundation.pEp.pitytest.TestSuite;
import foundation.pEp.pitytest.TestUnit;
import foundation.pEp.pitytest.utils.TestUtils;
import java.lang.ref.WeakReference;
import java.util.Vector;
import static foundation.pEp.pitytest.TestLogger.log;
/*
Test for JNI-135 - Heavy memory consumption - memory leaks
relates to:
* JNI-148 - Mem-mgmt: Defined behaviour of Message.close()
* JNI-160 - Mem-mgmt: Resource Instrumentation for class Message
We are simply encrypting and decrypting in a cycles with 2 own identities alice and bob.
The idea is that you fire up your mem-monitoring tool of choice and convince yourself about the
reality of the amount leaked memory in relation to the number of cycles.
Since JNI-160, this test also prints the result of Message.getInstanceCount(). Please see ticket for more details.
This test suite proofs 3 things:
* If you ignore mem-mgmt, you WILL leak memory
* If you do mem-mgmt right, you DONT leak memory
* If you lost all references to an unreleased message obj, it will be unreleasable forever.
To experiment with this, you can run a single test only and make use of the options:
* repeatCount - how many iterations/cycles
* msgSizeMB - attachement size of one message
* EncFormat - the encryption format
To run a single test only, comment out the last line:
"TestSuite.getDefault().run();"
and run the TestUnit directly using TestUnit.run():
new TestUnit<ctxtype>("bla", new ctxType(), ctx -> {
// code
}).run();
*/
// FOR TEST CONFIG DO NOT TWEAK HERE, THESE ARE DEFAULTS
class Jni135TestContext extends AbstractTestContext {
// Model
public TestModel<pEpTestIdentity, TestNode<pEpTestIdentity>> model = new TestModel(pEpTestIdentity::new, TestNode::new);
// Basic
public Engine engine;
// Identities
public Identity alice;
public Identity bob;
// Test config defaults
public int repeatCount = 2000;
public int msgSizeMB = 1;
public Message.EncFormat encFormat = Message.EncFormat.PEPEncInlineEA;
public Jni135TestContext init() throws Throwable {
engine = new Engine();
// fetch data for the idents
alice = model.getIdent(Role.ALICE).pEpIdent;
bob = model.getIdent(Role.BOB).pEpIdent;
// create keys etc..
alice = engine.myself(alice);
bob = engine.myself(bob);
class Jni135TestContext extends CTXBase {
@Override
public CTXBase init() throws Throwable {
super.init();
return this;
}
}
class TestAlice {
public static void gc() {
// log("gc start");
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while (ref.get() != null) {
System.gc();
public static void proofLeakNonLeak(Jni135TestContext ctx, boolean wannaLeak) {
int cycles = 0;
while (cycles < ctx.repeatCount) {
Message msg1Plain = AdapterTestUtils.makeNewTestMessage(ctx.alice, ctx.bob, Message.Direction.Outgoing);
Blob bigBlob = AdapterTestUtils.makeNewTestBlob(ctx.msgSizeMB * 1024 * 1024, "atti1", "text/plain");
Vector<Blob> atts = new Vector<Blob>();
atts.add(bigBlob);
msg1Plain.setAttachments(atts);
Message msg1Enc = ctx.engine.encrypt_message(msg1Plain, null, ctx.encFormat);
decrypt_message_Return decRet = ctx.engine.decrypt_message(msg1Enc, null, 0);
assert decRet != null : "could not decrypt message";
if (!wannaLeak) {
decRet.dst.close();
msg1Enc.close();
msg1Plain.close();
log("cycle nr: " + cycles++ + " / Message.getInstanceCount(): " + Message.getInstanceCount());
assert Message.getInstanceCount() == 0 : "Leaking messages";
} else {
log("cycle nr: " + cycles++ + " / Message.getInstanceCount(): " + Message.getInstanceCount());
assert Message.getInstanceCount() > 0 : "We should be leaking messages, actually";
}
}
// log("gc end");
}
public static void main(String[] args) throws Exception {
// TestUtils.readKey();
TestSuite.getDefault().setVerbose(true);
TestSuite.getDefault().setTestColor(TestUtils.TermColor.GREEN);
CTXBase jni135Ctx = new Jni135TestContext();
Engine.setDebugLogEnabled(false);
new TestUnit<CTXBase>("setDir() == getDir() ", new Jni135TestContext(), ctx -> {
ctx.alice = ctx.engine.myself(ctx.alice);
ctx.bob = ctx.engine.myself(ctx.bob);
int cycles = 0;
while (true) {
Message msg1Plain = AdapterTestUtils.makeNewTestMessage(ctx.alice, ctx.bob, Message.Direction.Outgoing);
Blob bigBlob = AdapterTestUtils.makeNewTestBlob(10000000, "atti1", "text/plain");
Vector<Blob> atts = new Vector<Blob>();
atts.add(bigBlob);
msg1Plain.setAttachments(atts);
if (false) {
Message msg1Enc = ctx.engine.encrypt_message(msg1Plain, null, Message.EncFormat.PEP);
decrypt_message_Return decRet = ctx.engine.decrypt_message(msg1Enc, null, 0);
assert decRet != null : "could not decrypt message";
// decRet.dst.close();
// msg1Enc.close();
// gc();
// msg1Plain.close();
}
log("cycles: " + cycles++);
}
}).run();
{
Jni135TestContext ctxDontLeak = new Jni135TestContext();
// Config
ctxDontLeak.repeatCount = 3;
ctxDontLeak.msgSizeMB = 1;
new TestUnit<Jni135TestContext>("Proof leaking messages ", ctxDontLeak, ctx -> {
proofLeakNonLeak(ctx, false);
});
}
{
Jni135TestContext ctxDoLeak = new Jni135TestContext();
// Config
ctxDoLeak.repeatCount = 3;
ctxDoLeak.msgSizeMB = 1;
new TestUnit<Jni135TestContext>("Proof NOT leaking messages ", ctxDoLeak, ctx -> {
proofLeakNonLeak(ctx, true);
});
}
// TestSuite.getDefault().run();
{
Jni135TestContext ctxLostRefs = new Jni135TestContext();
// Config
ctxLostRefs.repeatCount = 3;
ctxLostRefs.msgSizeMB = 1;
new TestUnit<Jni135TestContext>("Lost refs cant be recovered", ctxLostRefs, ctx -> {
try {
proofLeakNonLeak(ctx, false);
assert false : "Lost references to message objects should never be recoverable";
} catch (Throwable t) {
}
// To run one individual test only
})//.run(); // comment this in
;
}
// AND
TestSuite.getDefault().run(); // comment this out
}
}


Loading…
Cancel
Save