1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <fbl/algorithm.h>
6#include <fbl/unique_ptr.h>
7#include <perftest/results.h>
8#include <unittest/unittest.h>
9
10// Add terminator to a string buffer registered with fmemopen().
11static bool FixUpFileBuffer(FILE* fp, char* buf, size_t buf_size) {
12    ASSERT_FALSE(ferror(fp));
13    size_t data_size = ftell(fp);
14    ASSERT_LT(data_size, buf_size);
15    buf[data_size] = '\0';
16    ASSERT_EQ(fclose(fp), 0);
17    return true;
18}
19
20static bool test_json_output() {
21    BEGIN_TEST;
22
23    perftest::ResultsSet results;
24    perftest::TestCaseResults* test_case =
25        results.AddTestCase("results_test", "ExampleNullSyscall", "nanoseconds");
26    // Fill out some example data.
27    for (int val = 101; val <= 105; ++val) {
28        test_case->AppendValue(val);
29    }
30
31    // Write the JSON output to a buffer in memory.
32    char buf[1000];
33    FILE* fp = fmemopen(buf, sizeof(buf), "w+");
34    ASSERT_NONNULL(fp);
35    results.WriteJSON(fp);
36    ASSERT_TRUE(FixUpFileBuffer(fp, buf, sizeof(buf)));
37
38    // Test the JSON output.
39    const char* expected = R"JSON([{"label":"ExampleNullSyscall","test_suite":"results_test","unit":"nanoseconds","values":[101.000000,102.000000,103.000000,104.000000,105.000000]}])JSON";
40    EXPECT_STR_EQ(expected, buf, "");
41
42    END_TEST;
43}
44
45static bool test_summary_statistics() {
46    BEGIN_TEST;
47
48    perftest::ResultsSet results;
49    perftest::TestCaseResults* test_case =
50        results.AddTestCase("results_test", "ExampleNullSyscall", "nanoseconds");
51    // Fill out some example data in a non-sorted order.
52    test_case->AppendValue(200);
53    test_case->AppendValue(6);
54    test_case->AppendValue(100);
55    test_case->AppendValue(110);
56
57    perftest::SummaryStatistics stats = test_case->GetSummaryStatistics();
58    EXPECT_EQ(stats.min, 6);
59    EXPECT_EQ(stats.max, 200);
60    EXPECT_EQ(stats.mean, 104);
61    EXPECT_EQ(static_cast<int>(stats.std_dev), 68);
62    // There is an even number of values, so the median is interpolated.
63    EXPECT_EQ(stats.median, (100 + 110) / 2);
64
65    test_case->AppendValue(300);
66    stats = test_case->GetSummaryStatistics();
67    // There is an odd number of values, so the median is not interpolated.
68    EXPECT_EQ(stats.median, 110);
69
70    END_TEST;
71}
72
73// Test escaping special characters in strings in JSON output.
74static bool test_json_string_escaping() {
75    BEGIN_TEST;
76
77    char buf[1000];
78    FILE* fp = fmemopen(buf, sizeof(buf), "w+");
79    ASSERT_NONNULL(fp);
80    perftest::WriteJSONString(fp, "foo \"bar\" \\ \n \xff");
81    ASSERT_TRUE(FixUpFileBuffer(fp, buf, sizeof(buf)));
82
83    const char* expected = "\"foo \\\"bar\\\" \\\\ \\u000a \\u00ff\"";
84    EXPECT_STR_EQ(expected, buf, "");
85
86    END_TEST;
87}
88
89BEGIN_TEST_CASE(perf_results_output_tests)
90RUN_TEST(test_json_output)
91RUN_TEST(test_summary_statistics)
92RUN_TEST(test_json_string_escaping)
93END_TEST_CASE(perf_results_output_tests)
94