1 /* Copyright (c) 2017, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include "file_test.h"
16 
17 #include <assert.h>
18 #include <string.h>
19 
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 #include <gtest/gtest.h>
25 
26 #include <openssl/err.h>
27 
28 
29 std::string GetTestData(const char *path);
30 
31 class StringLineReader : public FileTest::LineReader {
32  public:
StringLineReader(const std::string & data)33   explicit StringLineReader(const std::string &data)
34       : data_(data), offset_(0) {}
35 
ReadLine(char * out,size_t len)36   FileTest::ReadResult ReadLine(char *out, size_t len) override {
37     assert(len > 0);
38     if (offset_ == data_.size()) {
39       return FileTest::kReadEOF;
40     }
41 
42     size_t idx = data_.find('\n', offset_);
43     if (idx == std::string::npos) {
44       idx = data_.size();
45     } else {
46       idx++;  // Include the newline.
47     }
48 
49     if (idx - offset_ > len - 1) {
50       ADD_FAILURE() << "Line too long.";
51       return FileTest::kReadError;
52     }
53 
54     memcpy(out, data_.data() + offset_, idx - offset_);
55     out[idx - offset_] = '\0';
56     offset_ = idx;
57     return FileTest::kReadSuccess;
58   }
59 
60  private:
61   std::string data_;
62   size_t offset_;
63 
64   StringLineReader(const StringLineReader &) = delete;
65   StringLineReader &operator=(const StringLineReader &) = delete;
66 };
67 
FileTestGTest(const char * path,std::function<void (FileTest *)> run_test)68 void FileTestGTest(const char *path, std::function<void(FileTest *)> run_test) {
69   std::unique_ptr<StringLineReader> reader(
70       new StringLineReader(GetTestData(path)));
71   FileTest t(std::move(reader), nullptr, false);
72 
73   while (true) {
74     switch (t.ReadNext()) {
75       case FileTest::kReadError:
76         ADD_FAILURE() << "Error reading test.";
77         return;
78       case FileTest::kReadEOF:
79         return;
80       case FileTest::kReadSuccess:
81         break;
82     }
83 
84     const testing::TestResult *test_result =
85         testing::UnitTest::GetInstance()->current_test_info()->result();
86     int before_part_count = test_result->total_part_count();
87 
88     SCOPED_TRACE(testing::Message() << path << ", line " << t.start_line());
89     run_test(&t);
90 
91     // Check for failures from the most recent test.
92     bool failed = false;
93     for (int i = before_part_count; i < test_result->total_part_count(); i++) {
94       if (test_result->GetTestPartResult(i).failed()) {
95         failed = true;
96         break;
97       }
98     }
99 
100     // Clean up the error queue for the next test, reporting it on failure.
101     if (failed) {
102       ERR_print_errors_fp(stdout);
103     } else {
104       ERR_clear_error();
105     }
106   }
107 }
108