Echo CAVP comments in the output.

Comments in CAVP are semantically important and we need to copy them
from the input to the output.

Change-Id: Ib798c4ad79de924487d0c4a0f8fc16b757e766d8
Reviewed-on: https://boringssl-review.googlesource.com/16725
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/test/file_test.cc b/crypto/test/file_test.cc
index 87a6b96..5bc5fb4 100644
--- a/crypto/test/file_test.cc
+++ b/crypto/test/file_test.cc
@@ -30,8 +30,9 @@
 #include "../internal.h"
 
 
-FileTest::FileTest(std::unique_ptr<FileTest::LineReader> reader)
-    : reader_(std::move(reader)) {}
+FileTest::FileTest(std::unique_ptr<FileTest::LineReader> reader,
+                   std::function<void(const std::string &)> comment_callback)
+    : reader_(std::move(reader)), comment_callback_(comment_callback) {}
 
 FileTest::~FileTest() {}
 
@@ -121,12 +122,15 @@
         // Delimit instruction block from test with a blank line.
         current_test_ += "\r\n";
       }
-    } else if (buf[0] == '#' ||
-               strcmp("[B.4.2 Key Pair Generation by Testing Candidates]\r\n",
+    } else if (buf[0] == '#') {
+      if (comment_callback_) {
+        comment_callback_(buf.get());
+      }
+      // Otherwise ignore comments.
+    } else if (strcmp("[B.4.2 Key Pair Generation by Testing Candidates]\r\n",
                       buf.get()) == 0) {
-      // Ignore comments. The above instruction-like line is treated as a
-      // comment because the FIPS lab's request files are hopelessly
-      // inconsistent.
+      // The above instruction-like line is ignored because the FIPS lab's
+      // request files are hopelessly inconsistent.
     } else if (buf[0] == '[') {  // Inside an instruction block.
       is_at_new_instruction_block_ = true;
       if (start_line_ != 0) {
@@ -399,14 +403,26 @@
   FileLineReader &operator=(const FileLineReader &) = delete;
 };
 
-int FileTestMainSilent(FileTestFunc run_test, void *arg, const char *path) {
-  std::unique_ptr<FileLineReader> reader(new FileLineReader(path));
+int FileTestMain(FileTestFunc run_test, void *arg, const char *path) {
+  FileTest::Options opts;
+  opts.callback = run_test;
+  opts.arg = arg;
+  opts.path = path;
+
+  return FileTestMain(opts);
+}
+
+int FileTestMain(const FileTest::Options &opts) {
+  std::unique_ptr<FileLineReader> reader(
+      new FileLineReader(opts.path));
   if (!reader->is_open()) {
-    fprintf(stderr, "Could not open file %s: %s.\n", path, strerror(errno));
+    fprintf(stderr, "Could not open file %s: %s.\n", opts.path,
+            strerror(errno));
     return 1;
   }
 
-  FileTest t(std::move(reader));
+  FileTest t(std::move(reader), opts.comment_callback);
+
   bool failed = false;
   while (true) {
     FileTest::ReadResult ret = t.ReadNext();
@@ -416,7 +432,7 @@
       break;
     }
 
-    bool result = run_test(&t, arg);
+    bool result = opts.callback(&t, opts.arg);
     if (t.HasAttribute("Error")) {
       if (result) {
         t.PrintLine("Operation unexpectedly succeeded.");
@@ -443,13 +459,9 @@
     }
   }
 
-  return failed ? 1 : 0;
-}
-
-int FileTestMain(FileTestFunc run_test, void *arg, const char *path) {
-  int result = FileTestMainSilent(run_test, arg, path);
-  if (!result) {
+  if (!opts.silent && !failed) {
     printf("PASS\n");
   }
-  return result;
+
+  return failed ? 1 : 0;
 }
diff --git a/crypto/test/file_test.h b/crypto/test/file_test.h
index 70629f3..8c476c4 100644
--- a/crypto/test/file_test.h
+++ b/crypto/test/file_test.h
@@ -84,6 +84,8 @@
 // consumed. When a test completes, if any attributes or insturctions haven't
 // been processed, the framework reports an error.
 
+class FileTest;
+typedef bool (*FileTestFunc)(FileTest *t, void *arg);
 
 class FileTest {
  public:
@@ -99,7 +101,23 @@
     virtual ReadResult ReadLine(char *out, size_t len) = 0;
   };
 
-  explicit FileTest(std::unique_ptr<LineReader> reader);
+  struct Options {
+    // path is the path to the input file.
+    const char *path = nullptr;
+    // callback is called for each test. It should get the parameters from this
+    // object and signal any errors by returning false.
+    FileTestFunc callback = nullptr;
+    // arg is an opaque pointer that is passed to |callback|.
+    void *arg = nullptr;
+    // silent suppressed the "PASS" string that is otherwise printed after
+    // successful runs.
+    bool silent = false;
+    // comment_callback is called after each comment in the input is parsed.
+    std::function<void(const std::string&)> comment_callback;
+  };
+
+  explicit FileTest(std::unique_ptr<LineReader> reader,
+                    std::function<void(const std::string &)> comment_callback);
   ~FileTest();
 
   // ReadNext reads the next test from the file. It returns |kReadSuccess| if
@@ -197,12 +215,14 @@
 
   bool is_at_new_instruction_block_ = false;
 
+  // comment_callback_, if set, is a callback function that is called with the
+  // contents of each comment as they are parsed.
+  std::function<void(const std::string&)> comment_callback_;
+
   FileTest(const FileTest &) = delete;
   FileTest &operator=(const FileTest &) = delete;
 };
 
-typedef bool (*FileTestFunc)(FileTest *t, void *arg);
-
 // FileTestMain runs a file-based test out of |path| and returns an exit code
 // suitable to return out of |main|. |run_test| should return true on pass and
 // false on failure. FileTestMain also implements common handling of the 'Error'
@@ -216,9 +236,8 @@
 // subsequent tests.
 int FileTestMain(FileTestFunc run_test, void *arg, const char *path);
 
-// FileTestMainSilent behaves like FileTestMain but does not print a final
-// FAIL/PASS message to stdout.
-int FileTestMainSilent(FileTestFunc run_test, void *arg, const char *path);
+// FileTestMain accepts a larger number of options via a struct.
+int FileTestMain(const FileTest::Options &opts);
 
 // FileTestGTest behaves like FileTestMain, but for GTest. |path| must be the
 // name of a test file embedded in the test binary.
diff --git a/crypto/test/file_test_gtest.cc b/crypto/test/file_test_gtest.cc
index 90d12bf..9d3c3e4 100644
--- a/crypto/test/file_test_gtest.cc
+++ b/crypto/test/file_test_gtest.cc
@@ -66,7 +66,7 @@
 void FileTestGTest(const char *path, std::function<void(FileTest *)> run_test) {
   std::unique_ptr<StringLineReader> reader(
       new StringLineReader(GetTestData(path)));
-  FileTest t(std::move(reader));
+  FileTest t(std::move(reader), nullptr);
 
   while (true) {
     switch (t.ReadNext()) {
diff --git a/fipstools/cavp_aes_gcm_test.cc b/fipstools/cavp_aes_gcm_test.cc
index 21d03bf..7278cea 100644
--- a/fipstools/cavp_aes_gcm_test.cc
+++ b/fipstools/cavp_aes_gcm_test.cc
@@ -153,11 +153,11 @@
 
   TestCtx ctx = {aead};
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(test_fn, &ctx, argv[3]);
+  FileTest::Options opts;
+  opts.path = argv[3];
+  opts.callback = test_fn;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_aes_test.cc b/fipstools/cavp_aes_test.cc
index ad1d50c..6c0cf3c 100644
--- a/fipstools/cavp_aes_test.cc
+++ b/fipstools/cavp_aes_test.cc
@@ -217,11 +217,11 @@
 
   TestCtx ctx = {cipher, has_iv, test_mode};
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestCipher, &ctx, argv[3]);
+  FileTest::Options opts;
+  opts.path = argv[3];
+  opts.callback = TestCipher;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_ctr_drbg_test.cc b/fipstools/cavp_ctr_drbg_test.cc
index b18c437..30a1a15 100644
--- a/fipstools/cavp_ctr_drbg_test.cc
+++ b/fipstools/cavp_ctr_drbg_test.cc
@@ -97,11 +97,10 @@
     return usage(argv[0]);
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n# CTR_DRBG options: AES-256 no df\r\n\r\n");
-
-  return FileTestMainSilent(TestCTRDRBG, nullptr, argv[1]);
+  FileTest::Options opts;
+  opts.path = argv[1];
+  opts.callback = TestCTRDRBG;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_ecdsa2_keypair_test.cc b/fipstools/cavp_ecdsa2_keypair_test.cc
index 5cb0f5b..d1fcead 100644
--- a/fipstools/cavp_ecdsa2_keypair_test.cc
+++ b/fipstools/cavp_ecdsa2_keypair_test.cc
@@ -84,11 +84,10 @@
     return 1;
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestECDSA2KeyPair, nullptr, argv[1]);
+  FileTest::Options opts;
+  opts.path = argv[1];
+  opts.callback = TestECDSA2KeyPair;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_ecdsa2_pkv_test.cc b/fipstools/cavp_ecdsa2_pkv_test.cc
index a5c09e7..d823e7a 100644
--- a/fipstools/cavp_ecdsa2_pkv_test.cc
+++ b/fipstools/cavp_ecdsa2_pkv_test.cc
@@ -57,11 +57,10 @@
     return 1;
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestECDSA2PKV, nullptr, argv[1]);
+  FileTest::Options opts;
+  opts.path = argv[1];
+  opts.callback = TestECDSA2PKV;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_ecdsa2_siggen_test.cc b/fipstools/cavp_ecdsa2_siggen_test.cc
index 2d6c79e..60c1c87 100644
--- a/fipstools/cavp_ecdsa2_siggen_test.cc
+++ b/fipstools/cavp_ecdsa2_siggen_test.cc
@@ -115,11 +115,10 @@
     return 1;
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(test_func, nullptr, argv[2]);
+  FileTest::Options opts;
+  opts.path = argv[2];
+  opts.callback = test_func;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_ecdsa2_sigver_test.cc b/fipstools/cavp_ecdsa2_sigver_test.cc
index ea7649e..f3fd4b1 100644
--- a/fipstools/cavp_ecdsa2_sigver_test.cc
+++ b/fipstools/cavp_ecdsa2_sigver_test.cc
@@ -75,11 +75,10 @@
     return 1;
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestECDSA2SigVer, nullptr, argv[1]);
+  FileTest::Options opts;
+  opts.path = argv[1];
+  opts.callback = TestECDSA2SigVer;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_hmac_test.cc b/fipstools/cavp_hmac_test.cc
index 9c4f221..59c7e10 100644
--- a/fipstools/cavp_hmac_test.cc
+++ b/fipstools/cavp_hmac_test.cc
@@ -94,11 +94,10 @@
     return usage(argv[0]);
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestHMAC, nullptr, argv[1]);
+  FileTest::Options opts;
+  opts.path = argv[1];
+  opts.callback = TestHMAC;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_keywrap_test.cc b/fipstools/cavp_keywrap_test.cc
index 19f8ba0..c7270df 100644
--- a/fipstools/cavp_keywrap_test.cc
+++ b/fipstools/cavp_keywrap_test.cc
@@ -115,11 +115,11 @@
 
   TestCtx ctx = {encrypt};
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestCipher, &ctx, argv[3]);
+  FileTest::Options opts;
+  opts.path = argv[3];
+  opts.callback = TestCipher;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_rsa2_keygen_test.cc b/fipstools/cavp_rsa2_keygen_test.cc
index a96404d..fa8d658 100644
--- a/fipstools/cavp_rsa2_keygen_test.cc
+++ b/fipstools/cavp_rsa2_keygen_test.cc
@@ -85,11 +85,10 @@
     return 1;
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestRSA2KeyGen, nullptr, argv[1]);
+  FileTest::Options opts;
+  opts.path = argv[1];
+  opts.callback = TestRSA2KeyGen;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_rsa2_siggen_test.cc b/fipstools/cavp_rsa2_siggen_test.cc
index ad32c68..063b89d 100644
--- a/fipstools/cavp_rsa2_siggen_test.cc
+++ b/fipstools/cavp_rsa2_siggen_test.cc
@@ -119,11 +119,11 @@
     return 1;
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestRSA2SigGen, &ctx, argv[2]);
+  FileTest::Options opts;
+  opts.path = argv[2];
+  opts.callback = TestRSA2SigGen;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_rsa2_sigver_test.cc b/fipstools/cavp_rsa2_sigver_test.cc
index bf1ea2d..cbcfc1f 100644
--- a/fipstools/cavp_rsa2_sigver_test.cc
+++ b/fipstools/cavp_rsa2_sigver_test.cc
@@ -115,11 +115,11 @@
     return 1;
   }
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestRSA2SigVer, &ctx, argv[2]);
+  FileTest::Options opts;
+  opts.path = argv[2];
+  opts.callback = TestRSA2SigVer;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_sha_monte_test.cc b/fipstools/cavp_sha_monte_test.cc
index 1609c98..d6f2fb0 100644
--- a/fipstools/cavp_sha_monte_test.cc
+++ b/fipstools/cavp_sha_monte_test.cc
@@ -92,11 +92,11 @@
 
   TestCtx ctx = {std::string(argv[1])};
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestSHAMonte, &ctx, argv[2]);
+  FileTest::Options opts;
+  opts.path = argv[2];
+  opts.callback = TestSHAMonte;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_sha_test.cc b/fipstools/cavp_sha_test.cc
index 131866a..aae25c1 100644
--- a/fipstools/cavp_sha_test.cc
+++ b/fipstools/cavp_sha_test.cc
@@ -86,11 +86,11 @@
 
   TestCtx ctx = {std::string(argv[1])};
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
-  return FileTestMainSilent(TestSHA, &ctx, argv[2]);
+  FileTest::Options opts;
+  opts.path = argv[2];
+  opts.callback = TestSHA;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_tdes_test.cc b/fipstools/cavp_tdes_test.cc
index ad608de..d1c10ff 100644
--- a/fipstools/cavp_tdes_test.cc
+++ b/fipstools/cavp_tdes_test.cc
@@ -331,12 +331,12 @@
   bool has_iv = cipher_name != "des-ede" && cipher_name != "des-ede3";
   TestCtx ctx = {cipher, has_iv, test_mode};
 
-  printf("# Generated by");
-  for (int i = 0; i < argc; i++) {
-    printf(" %s", argv[i]);
-  }
-  printf("\r\n\r\n");
-
   FileTestFunc test_fn = test_mode == TestCtx::kKAT ? &TestKAT : &TestMCT;
-  return FileTestMainSilent(test_fn, &ctx, argv[3]);
+  FileTest::Options opts;
+  opts.path = argv[3];
+  opts.callback = test_fn;
+  opts.arg = &ctx;
+  opts.silent = true;
+  opts.comment_callback = EchoComment;
+  return FileTestMain(opts);
 }
diff --git a/fipstools/cavp_test_util.cc b/fipstools/cavp_test_util.cc
index 98be3fa..87a3b92 100644
--- a/fipstools/cavp_test_util.cc
+++ b/fipstools/cavp_test_util.cc
@@ -225,3 +225,7 @@
   t->PrintLine("No supported digest function specified.");
   return nullptr;
 }
+
+void EchoComment(const std::string& comment) {
+  fwrite(comment.c_str(), comment.size(), 1, stdout);
+}
diff --git a/fipstools/cavp_test_util.h b/fipstools/cavp_test_util.h
index 54fd57d..0cbd9a7 100644
--- a/fipstools/cavp_test_util.h
+++ b/fipstools/cavp_test_util.h
@@ -54,6 +54,8 @@
 
 const EVP_MD *GetDigestFromInstruction(FileTest *t);
 
+void EchoComment(const std::string& comment);
+
 int cavp_aes_gcm_test_main(int argc, char **argv);
 int cavp_aes_test_main(int argc, char **argv);
 int cavp_ctr_drbg_test_main(int argc, char **argv);