Output test configs for Bazel builds.

This change amends generate_build_files.py so that Bazel output includes
rules for the (no-Go) tests.

Change-Id: I0c8dca599d6f828191eb665332af3193c650bc1a
Reviewed-on: https://boringssl-review.googlesource.com/5102
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/util/generate_build_files.py b/util/generate_build_files.py
index bee46ca..a3661d3 100644
--- a/util/generate_build_files.py
+++ b/util/generate_build_files.py
@@ -19,6 +19,7 @@
 import os
 import subprocess
 import sys
+import json
 
 
 # OS_ARCH_COMBOS maps from OS and platform to the OpenSSL assembly "style" for
@@ -208,6 +209,76 @@
         self.PrintVariableSection(
             out, 'crypto_sources_%s' % arch, asm_files)
 
+    with open('BUILD.generated_tests', 'w+') as out:
+      out.write(self.header)
+
+      out.write('test_support_sources = [\n')
+      for filename in files['test_support']:
+        if os.path.basename(filename) == 'malloc.cc':
+          continue
+        out.write('    "%s",\n' % filename)
+      out.write('] + glob(["src/crypto/test/*.h"])\n\n')
+
+      name_counts = {}
+      for test in files['tests']:
+        name = os.path.basename(test[0])
+        name_counts[name] = name_counts.get(name, 0) + 1
+
+      first = True
+      for test in files['tests']:
+        name = os.path.basename(test[0])
+        if name_counts[name] > 1:
+          if '/' in test[1]:
+            name += '_' + os.path.splitext(os.path.basename(test[1]))[0]
+          else:
+            name += '_' + test[1].replace('-', '_')
+
+        if not first:
+          out.write('\n')
+        first = False
+
+        src_prefix = 'src/' + test[0]
+        for src in files['test']:
+          if src.startswith(src_prefix):
+            src = src
+            break
+        else:
+          raise ValueError("Can't find source for %s" % test[0])
+
+        out.write('cc_test(\n')
+        out.write('    name = "%s",\n' % name)
+        out.write('    size = "small",\n')
+        out.write('    srcs = ["%s"] + test_support_sources,\n' % src)
+
+        data_files = []
+        if len(test) > 1:
+
+          out.write('    args = [\n')
+          for arg in test[1:]:
+            if '/' in arg:
+              out.write('        "$(location src/%s)",\n' % arg)
+              data_files.append('src/%s' % arg)
+            else:
+              out.write('        "%s",\n' % arg)
+          out.write('    ],\n')
+
+        out.write('    copts = boringssl_copts,\n')
+
+        if len(data_files) > 0:
+          out.write('    data = [\n')
+          for filename in data_files:
+            out.write('        "%s",\n' % filename)
+          out.write('    ],\n')
+
+        if 'ssl/' in test[0]:
+          out.write('    deps = [\n')
+          out.write('        ":crypto",\n')
+          out.write('        ":ssl",\n')
+          out.write('    ],\n')
+        else:
+          out.write('    deps = [":crypto"],\n')
+        out.write(')\n')
+
 
 def FindCMakeFiles(directory):
   """Returns list of all CMakeLists.txt files recursively in directory."""
@@ -410,6 +481,23 @@
   crypto_internal_h_files = FindHeaderFiles(
       os.path.join('src', 'crypto'), NoTests)
 
+  with open('src/util/all_tests.json', 'r') as f:
+    tests = json.load(f)
+  test_binaries = set([test[0] for test in tests])
+  test_sources = set([
+      test.replace('.cc', '').replace('.c', '').replace(
+          'src/',
+          '')
+      for test in test_c_files])
+  if test_binaries != test_sources:
+    print 'Test sources and configured tests do not match'
+    a = test_binaries.difference(test_sources)
+    if len(a) > 0:
+      print 'These tests are configured without sources: ' + str(a)
+    b = test_sources.difference(test_binaries)
+    if len(b) > 0:
+      print 'These test sources are not configured: ' + str(b)
+
   files = {
       'crypto': crypto_c_files,
       'crypto_headers': crypto_h_files,
@@ -420,6 +508,7 @@
       'tool': tool_cc_files,
       'test': test_c_files,
       'test_support': test_support_cc_files,
+      'tests': tests,
   }
 
   asm_outputs = sorted(WriteAsmFiles(ReadPerlAsmOperations()).iteritems())