content: package dk.alexandra.fresco.suite.spdz2k.synchronization;
  
  import dk.alexandra.fresco.framework.Application;
  import dk.alexandra.fresco.framework.DRes;
  import dk.alexandra.fresco.framework.TestThreadRunner.TestThread;
  import dk.alexandra.fresco.framework.TestThreadRunner.TestThreadFactory;
  import dk.alexandra.fresco.framework.builder.numeric.ProtocolBuilderNumeric;
  import dk.alexandra.fresco.framework.network.Network;
  import dk.alexandra.fresco.framework.sce.evaluator.EvaluationStrategy;
  import dk.alexandra.fresco.framework.util.AesCtrDrbg;
  import dk.alexandra.fresco.framework.value.SInt;
  import dk.alexandra.fresco.suite.ProtocolSuiteNumeric;
  import dk.alexandra.fresco.suite.spdz2k.AbstractSpdz2kTest;
  import dk.alexandra.fresco.suite.spdz2k.Spdz2kProtocolSuiteK64;
  import dk.alexandra.fresco.suite.spdz2k.datatypes.CompUInt128;
  import dk.alexandra.fresco.suite.spdz2k.datatypes.CompUInt128Factory;
  import dk.alexandra.fresco.suite.spdz2k.datatypes.CompUIntFactory;
  import dk.alexandra.fresco.suite.spdz2k.resource.Spdz2kResourcePool;
  import dk.alexandra.fresco.suite.spdz2k.resource.Spdz2kResourcePoolImpl;
  import dk.alexandra.fresco.suite.spdz2k.resource.storage.Spdz2kDummyDataSupplier;
  import dk.alexandra.fresco.suite.spdz2k.resource.storage.Spdz2kOpenedValueStoreImpl;
  import java.math.BigInteger;
  import java.util.function.Supplier;
  import org.junit.Assert;
  import org.junit.Test;
  
  public class TestSpdz2kRoundSynchronization extends
      AbstractSpdz2kTest<Spdz2kResourcePool<CompUInt128>> {
  
    @Test
    public void testFinishedEvalMacCheck() {
      runTest(new TestMacCheckEvalFinished<>(),
          EvaluationStrategy.SEQUENTIAL_BATCHED, 2);
    }
  
    @Override
    protected Spdz2kResourcePool<CompUInt128> createResourcePool(int playerId, int noOfParties,
        Supplier<Network> networkSupplier) {
      CompUIntFactory<CompUInt128> factory = new CompUInt128Factory();
      Spdz2kResourcePool<CompUInt128> resourcePool =
          new Spdz2kResourcePoolImpl<>(
              playerId,
              noOfParties, null,
              new Spdz2kOpenedValueStoreImpl<>(),
              new Spdz2kDummyDataSupplier<>(playerId, noOfParties, factory.createRandom(), factory),
              factory);
      resourcePool.initializeJointRandomness(networkSupplier, AesCtrDrbg::new, 32);
      return resourcePool;
    }
  
    @Override
    protected ProtocolSuiteNumeric<Spdz2kResourcePool<CompUInt128>> createProtocolSuite() {
      return new Spdz2kProtocolSuiteK64();
    }
  
    private static class TestMacCheckEvalFinished<ResourcePoolT extends Spdz2kResourcePool<CompUInt128>>
        extends TestThreadFactory<ResourcePoolT, ProtocolBuilderNumeric> {
  
      @Override
      public TestThread<ResourcePoolT, ProtocolBuilderNumeric> next() {
        return new TestThread<ResourcePoolT, ProtocolBuilderNumeric>() {
          @Override
          public void test() {
            Application<SInt, ProtocolBuilderNumeric> testApplication = root -> {
              DRes<SInt> left = root.numeric().known(BigInteger.ZERO);
              DRes<SInt> right = root.numeric().known(BigInteger.ONE);
              return root.numeric().mult(left, right);
            };
            // this tests verifies that the round synchronization logic works correctly when we have
            // do not have output protocols in our application but still open values during
            // multiplication
            runApplication(testApplication);
            Assert.assertFalse(
                "There should be no unchecked opened values after the evaluation has finished",
                conf.getResourcePool().getOpenedValueStore().hasPendingValues());
          }
        };
      }
    }
  
  }
  