boringssl/util/embed_test_data.go
David Benjamin 3ecd0a5fca Convert aes_test to GTest.
This introduces machinery to start embedding the test data files into
the crypto_test binary. Figuring out every CI's test data story is more
trouble than is worth it. The GTest FileTest runner is considerably
different from the old one:

- It returns void and expects failures to use the GTest EXPECT_* and
  ASSERT_* macros, rather than ExpectBytesEqual. This is more monkey
  work to convert, but ultimately less work to add new tests. I think
  it's also valuable for our FileTest and normal test patterns to align
  as much as possible. The line number is emitted via SCOPED_TRACE.

- I've intentionally omitted the Error attribute handling, since that
  doesn't work very well with the new callback. This means evp_test.cc
  will take a little more work to convert, but this is again to keep our
  two test patterns aligned.

- The callback takes a std::function rather than a C-style void pointer.
  This means we can go nuts with lambdas. It also places the path first
  so clang-format doesn't go nuts.

BUG=129

Change-Id: I0d1920a342b00e64043e3ea05f5f5af57bfe77b3
Reviewed-on: https://boringssl-review.googlesource.com/16507
Reviewed-by: Adam Langley <agl@google.com>
2017-05-23 22:33:25 +00:00

141 lines
4.0 KiB
Go

// Copyright (c) 2017, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
// embed_test_data generates a C++ source file which exports a function,
// GetTestData, which looks up the specified data files.
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"unicode"
)
func quote(in []byte) string {
var buf bytes.Buffer
buf.WriteByte('"')
for _, b := range in {
switch b {
case '\a':
buf.WriteString(`\a`)
case '\b':
buf.WriteString(`\b`)
case '\f':
buf.WriteString(`\f`)
case '\n':
buf.WriteString(`\n`)
case '\r':
buf.WriteString(`\r`)
case '\t':
buf.WriteString(`\t`)
case '\v':
buf.WriteString(`\v`)
case '"':
buf.WriteString(`\"`)
default:
if unicode.IsPrint(rune(b)) {
buf.WriteByte(b)
} else {
fmt.Fprintf(&buf, "\\x%02x", b)
}
}
}
buf.WriteByte('"')
return buf.String()
}
func main() {
fmt.Printf(`/* Copyright (c) 2017, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
/* This file is generated by:
`)
fmt.Printf(" * go run util/embed_test_data.go")
for _, arg := range os.Args[1:] {
fmt.Printf(" \\\n * %s", arg)
}
fmt.Printf(" */\n")
fmt.Printf(`
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <string>
`)
// MSVC limits the length of string constants, so we emit an array of
// them and concatenate at runtime. We could also use a single array
// literal, but this is less compact.
const chunkSize = 8192
for i, arg := range os.Args[1:] {
data, err := ioutil.ReadFile(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading %s: %s.\n", data, err)
os.Exit(1)
}
fmt.Printf("static const char *kData%d[] = {\n", i)
for i := 0; i < len(data); i += chunkSize {
chunk := chunkSize
if chunk > len(data)-i {
chunk = len(data) - i
}
fmt.Printf(" %s,\n", quote(data[i:i+chunk]))
}
fmt.Printf("};\n")
fmt.Printf("static const size_t kLen%d = %d;\n\n", i, len(data))
}
fmt.Printf(`static std::string AssembleString(const char **data, size_t len) {
std::string ret;
for (size_t i = 0; i < len; i += %d) {
size_t chunk = std::min(static_cast<size_t>(%d), len - i);
ret.append(data[i / %d], chunk);
}
return ret;
}
/* Silence -Wmissing-declarations. */
std::string GetTestData(const char *path);
std::string GetTestData(const char *path) {
`, chunkSize, chunkSize, chunkSize)
for i, arg := range os.Args[1:] {
fmt.Printf(" if (strcmp(path, %s) == 0) {\n", quote([]byte(arg)))
fmt.Printf(" return AssembleString(kData%d, kLen%d);\n", i, i)
fmt.Printf(" }\n")
}
fmt.Printf(` fprintf(stderr, "File not embedded: %%s.\n", path);
abort();
}
`)
}