Example #1
0
  /**
   * Test that applying data as an operation to get back a copy of the data works correctly.
   *
   * <p>The other tests assume that this test always passes.
   *
   * @param numIterations
   */
  public void testDataOperationEquivalence(int numIterations) {
    log.info("TESTING testDataOperationEquivalence");
    Random r = new Random(0);

    for (int iteration = 0; iteration < numIterations; iteration++) {
      log.info("Iteration: " + iteration);

      D d1 = domain.initialState();

      try {
        for (int i = 0; i < INITIAL_MUTATION_COUNT; i++) {
          O op = generator.randomOperation(d1, r);
          domain.apply(op, d1);

          D d2 = domain.initialState();
          domain.apply(domain.asOperation(d1), d2);

          if (!domain.equivalent(d1, d2)) {
            log.inconsistent(
                "DATA-AS-OPERATION BUG",
                "Subiteration: " + i,
                "Op from data: " + domain.asOperation(d1),
                "Data: " + d1,
                "Result of op on fresh state: " + d2);
          }
        }
      } catch (OperationException e) {
        logException("DATA-AS-OPERATION BUG? Operation exception", e);
      } catch (RuntimeException e) {
        logException("DATA-AS-OPERATION BUG? Runtime exception", e);
      }
    }
  }
Example #2
0
  public void testTransformDiamondProperty(int numIterations) {
    log.info("TESTING testTransformDiamondProperty");
    Random r = new Random(0);

    for (int iteration = 0; iteration < numIterations; iteration++) {
      log.info("Iteration: " + iteration);

      D d1 = domain.initialState();

      try {
        for (int i = 0; i < INITIAL_MUTATION_COUNT; i++) {
          O op = generator.randomOperation(d1, r);
          domain.apply(op, d1);
        }

        D d2 = copy(d1);

        for (int i = 0; i < FEATURE_ITERATION_COUNT; i++) {
          D original = copy(d1);

          O op1 = generator.randomOperation(original, r);
          O op2 = generator.randomOperation(original, r);

          domain.apply(op1, d1);
          domain.apply(op2, d2);

          D client = copy(d1);
          D server = copy(d2);

          OperationPair<O> pair = domain.transform(op1, op2);

          domain.apply(pair.serverOp(), d1);
          domain.apply(pair.clientOp(), d2);

          if (!domain.equivalent(d1, d2)) {
            log.inconsistent(
                "TRANSFORM BUG",
                "Subiteration: " + i,
                "Client: " + op1,
                "Server: " + op2,
                "Client': " + pair.clientOp(),
                "Server': " + pair.serverOp(),
                "Initial state: " + original,
                "Client state 1:" + client,
                "Client state 2:" + d1,
                "Server state 1:" + server,
                "Server state 2:" + d2);
          }
        }

      } catch (OperationException e) {
        logException("TRANSFORM BUG? Operation exception", e);
      } catch (TransformException e) {
        logException("TRANSFORM BUG? Transform exception", e);
      } catch (RuntimeException e) {
        logException("TRANSFORM BUG? Runtime exception", e);
      }
    }
  }
Example #3
0
  /** Test that (a.b).c = a.(b.c) */
  public void testCompositionAssociativity(int numIterations) {
    log.info("TESTING testCompositionAssociativity");
    Random r = new Random(0);

    for (int iteration = 0; iteration < numIterations; iteration++) {
      log.info("Iteration: " + iteration);

      try {
        D d1 = domain.initialState();

        for (int i = 0; i < INITIAL_MUTATION_COUNT; i++) {
          O op = generator.randomOperation(d1, r);
          domain.apply(op, d1);
        }

        D d2 = copy(d1);
        D d3 = copy(d1);

        for (int i = 0; i < FEATURE_ITERATION_COUNT; i++) {
          D backup = copy(d1);

          O op1 = generator.randomOperation(d1, r);
          domain.apply(op1, d1);
          O op2 = generator.randomOperation(d1, r);
          domain.apply(op2, d1);
          O op3 = generator.randomOperation(d1, r);
          domain.apply(op3, d1);

          O op12 = domain.compose(op2, op1);
          O op23 = domain.compose(op3, op2);

          domain.apply(op1, d2);
          domain.apply(op23, d2);

          domain.apply(op12, d3);
          domain.apply(op3, d3);

          if (!domain.equivalent(d2, d3)) {
            log.inconsistent(
                "COMPOSE ASSOCIATIVITY BUG",
                "Subiteration: " + i,
                "Op1: " + op1,
                "Op2: " + op2,
                "Op3: " + op2,
                "Op2.Op1: " + op12,
                "Op3.Op2: " + op23,
                "Initial state: " + backup,
                "State after Op3.(Op2.Op1): " + d3,
                "State after (Op3.Op2).Op1: " + d2);
          }
        }
      } catch (OperationException e) {
        logException("COMPOSE BUG? Operation exception", e);
      } catch (RuntimeException e) {
        logException("COMPOSE BUG? Runtime exception", e);
      }
    }
  }
Example #4
0
  private void testSimpleComposition(int numIterations, boolean emptyInitialState) {
    Random r = new Random(0);

    for (int iteration = 0; iteration < numIterations; iteration++) {
      log.info("Iteration: " + iteration);

      D d1 = domain.initialState();

      try {
        if (!emptyInitialState) {
          for (int i = 0; i < INITIAL_MUTATION_COUNT; i++) {
            O op = generator.randomOperation(d1, r);
            domain.apply(op, d1);
          }
        }

        D d2 = copy(d1);

        for (int i = 0; i < FEATURE_ITERATION_COUNT; i++) {
          D backup = copy(d1);

          O op1 = generator.randomOperation(d1, r);
          domain.apply(op1, d1);
          D after1 = copy(d1);
          O op2 = generator.randomOperation(d1, r);
          domain.apply(op2, d1);

          O composedOp = domain.compose(op2, op1);
          domain.apply(composedOp, d2);

          if (!domain.equivalent(d1, d2)) {
            log.inconsistent(
                "COMPOSE ASSOCIATIVITY BUG",
                "Subiteration: " + i,
                "Op1: " + op1,
                "Op2: " + op2,
                "Composed: " + composedOp,
                "Initial state: " + backup,
                "State after first: " + after1,
                "State after first then second: " + d1,
                "State after composed: " + d2);
          }
        }
      } catch (OperationException e) {
        logException("COMPOSE BUG? Operation exception", e);
      } catch (RuntimeException e) {
        logException("COMPOSE BUG? Runtime exception", e);
      }
    }
  }
Example #5
0
  public void testOperationInversion(int numIterations) {
    log.info("TESTING testOperationInversion");
    Random r = new Random(0);

    for (int iteration = 0; iteration < numIterations; iteration++) {
      log.info("Iteration: " + iteration);

      D d1 = domain.initialState();

      try {
        for (int i = 0; i < INITIAL_MUTATION_COUNT; i++) {
          O op = generator.randomOperation(d1, r);
          domain.apply(op, d1);
        }

        for (int i = 0; i < FEATURE_ITERATION_COUNT; i++) {
          log.info("X " + i);
          D backup = copy(d1);

          O op = generator.randomOperation(d1, r);
          domain.apply(op, d1);

          D afterOp = copy(d1);

          O reverse = domain.invert(op);
          domain.apply(reverse, d1);

          if (!domain.equivalent(d1, backup)) {
            log.inconsistent(
                "INVERSION BUG",
                "Subiteration: " + i,
                "Op: " + op,
                "Reverse: " + reverse,
                "Initial state: " + backup,
                "State after op: " + afterOp,
                "State after inverse: " + d1);
          }
        }
      } catch (OperationException e) {
        logException("COMPOSE BUG? Operation exception", e);
      } catch (RuntimeException e) {
        logException("COMPOSE BUG? Runtime exception", e);
      }
    }
  }
Example #6
0
  /**
   * Tests that transformation and composition are compatible
   *
   * <p>Assumes the diamond property of transformation
   *
   * <p>NOTE: This should be rewritten to do proper comparison of operations.
   *
   * @param numIterations
   */
  public void testTransformationCompositionCompatible(int numIterations) {
    log.info("TESTING testTransformationCompositionCompatible");
    Random r = new Random(0);

    for (int iteration = 0; iteration < numIterations; iteration++) {
      log.info("Iteration: " + iteration);

      D server = domain.initialState();

      try {
        for (int i = 0; i < INITIAL_MUTATION_COUNT; i++) {
          O op = generator.randomOperation(server, r);
          domain.apply(op, server);
        }

        D client = copy(server);

        for (int i = 0; i < FEATURE_ITERATION_COUNT; i++) {
          D original = copy(server);
          if (!domain.equivalent(client, server)) {
            log.inconsistent(
                "Sanity check failed: client and server not the same at start of test");
          }

          // Client is on the left for the first pass, but this
          // is reversed in the second pass (the meaning of the
          // variables "client" and "server" also reverses).
          //
          //        original (o)
          //          / \
          // client  a   b  server
          //        / \ /
          //       c   d
          //        \ /
          //        end (e)
          //

          O oa = generator.randomOperation(client, r);
          O ob = generator.randomOperation(server, r);

          domain.apply(oa, client);
          domain.apply(ob, server);

          D a = copy(client);
          D b = copy(server);

          OperationPair<O> pair1 = domain.transform(oa, ob);
          O bd = pair1.clientOp();
          O ad = pair1.serverOp();

          O ac = generator.randomOperation(a, r);
          domain.apply(ac, client);
          D c = copy(client);

          domain.apply(bd, server);
          D d = copy(server);

          D test = copy(a);
          domain.apply(ad, test);

          OperationPair<O> pair2 = domain.transform(ac, ad);
          O ce = pair2.serverOp();
          O de = pair2.clientOp();

          domain.apply(de, server);
          domain.apply(ce, client);
          D end = copy(client);

          O oc = domain.compose(ac, oa);
          O be = domain.compose(de, bd);

          // The property we want to test is that ce = ce2 and be = be2
          //
          OperationPair<O> pair3 = domain.transform(oc, ob);
          O ce2 = pair3.serverOp();
          O be2 = pair3.clientOp();

          D d1 = copy(c);
          domain.apply(ce2, d1);

          D d2 = copy(b);
          domain.apply(be2, d2);

          boolean ceOK = domain.equivalent(end, d1);
          boolean beOK = domain.equivalent(end, d2);
          if (!ceOK || !beOK) {
            log.inconsistent(
                "TRANSFORM AND COMPOSITION NOT COMPATIBLE",
                "Subiteration: " + i,
                ceOK ? "GOOD:" : "BAD:",
                "ce: " + ce,
                "ce2: " + ce2,
                beOK ? "GOOD:" : "BAD:",
                "be: " + be,
                "be2: " + be2,
                "-- States without compose: ",
                "        original (o)",
                "          / \\",
                " client  a   b  server",
                "        / \\ /",
                "       c   d",
                "        \\ /",
                "        end (e)",
                "o: " + original,
                "a: " + a,
                "b: " + b,
                "c: " + c,
                "d: " + d,
                "e: " + end);
          }
        }

      } catch (OperationException e) {
        logException("TRANSFORM BUG? Operation exception", e);
      } catch (TransformException e) {
        logException("TRANSFORM BUG? Transform exception", e);
      } catch (RuntimeException e) {
        logException("TRANSFORM BUG? Runtime exception", e);
      }
    }
  }