private void runTest(
      TestDataDescription description,
      boolean optimizedGenerics,
      String variant,
      Function1<File, Input> inputFactory,
      Function1<File, Output> outputFactory)
      throws Exception {
    File file =
        new File("test/resources/" + description.classSimpleName() + "-" + variant + ".ser");
    file.getParentFile().mkdirs();

    if (file.exists()) {
      Log.info(
          "Reading and testing "
              + description.classSimpleName()
              + " with mode '"
              + variant
              + "' from file "
              + file.getAbsolutePath());
      Input in = inputFactory.apply(file);
      readAndRunTest(description, optimizedGenerics, in);
      in.close();
    } else {
      Log.info(
          "Testing and writing "
              + description.classSimpleName()
              + " with mode '"
              + variant
              + "' to file "
              + file.getAbsolutePath());
      Output out = outputFactory.apply(file);
      try {
        runTestAndWrite(description, optimizedGenerics, out);
        out.close();
      } catch (Exception e) {
        // if anything failed (e.g. the initial test), we should delete the file as it may be empty
        // or corruped
        out.close();
        file.delete();
        throw e;
      }
    }
  }
 private void readAndRunTest(
     TestDataDescription<?> description, boolean optimizedGenerics, Input in)
     throws FileNotFoundException {
   TestData actual = kryo.readObject(in, description.testDataClass());
   roundTrip(
       optimizedGenerics ? description.lengthOptGenerics : description.lengthNonOptGenerics,
       optimizedGenerics
           ? description.unsafeLengthOptGenerics
           : description.unsafeLengthNonOptGenerics,
       actual);
   try {
     assertReflectionEquals(actual, description.testData);
   } catch (AssertionError e) {
     Log.info(
         "Serialization format is broken, please check "
             + getClass().getSimpleName()
             + "'s class doc to see"
             + " what this means and how to proceed.");
     throw e;
   }
 }