| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/performance/trace2json/convert.h" |
| |
| #include <gtest/gtest.h> |
| #include <rapidjson/document.h> |
| #include <rapidjson/istreamwrapper.h> |
| #include <src/lib/files/file.h> |
| |
| #if defined(__APPLE__) |
| #include <mach-o/dyld.h> |
| #endif |
| |
| #include <filesystem> |
| #include <fstream> |
| #include <sstream> |
| |
| namespace { |
| |
| using ::testing::Test; |
| |
| std::string GetSelfPath() { |
| std::string result; |
| #if defined(__APPLE__) |
| // Executable path can have relative references ("..") depending on how the |
| // app was launched. |
| uint32_t length = 0; |
| _NSGetExecutablePath(nullptr, &length); |
| result.resize(length); |
| _NSGetExecutablePath(&result[0], &length); |
| result.resize(length - 1); // Length included terminator. |
| #elif defined(__linux__) |
| // The realpath() call below will resolve the symbolic link. |
| result.assign("/proc/self/exe"); |
| #else |
| #error Write this for your platform. |
| #endif |
| |
| char fullpath[PATH_MAX]; |
| return std::string(realpath(result.c_str(), fullpath)); |
| } |
| |
| std::string GetTestDataPath() { |
| std::string path = GetSelfPath(); |
| size_t last_slash = path.rfind('/'); |
| if (last_slash == std::string::npos) { |
| path = "./"; |
| } else { |
| path.resize(last_slash + 1); |
| } |
| return path + "test_data/trace2json/"; |
| } |
| |
| // The gzip header contains a marker byte at offset 9 that contains which OS the file was generated |
| // on. The gzip files in test_data/ were generated on linux, so a naive comparison leads to the |
| // tests failing when they run on mac. |
| const ssize_t kNoIgnores[] = {-1}; |
| const ssize_t kIgnoreGzipOs[] = {9, -1}; |
| |
| void ConvertAndCompare(ConvertSettings settings, std::string expected_output_file, |
| const ssize_t* ignored_offsets) { |
| ASSERT_TRUE(ConvertTrace(settings)); |
| std::string actual_out, expected_out; |
| EXPECT_TRUE(files::ReadFileToString(settings.output_file_name, &actual_out)); |
| EXPECT_TRUE(files::ReadFileToString(expected_output_file, &expected_out)); |
| |
| for (int i = 0; ignored_offsets[i] >= 0; i++) { |
| const size_t offset = ignored_offsets[i]; |
| if (offset < actual_out.length()) { |
| actual_out[offset] = '\0'; |
| } |
| if (offset < expected_out.length()) { |
| expected_out[offset] = '\0'; |
| } |
| } |
| |
| // Not using EXPECT_EQ here as the trace files can be large, so failures create an unreasonable |
| // amount of error output. |
| EXPECT_TRUE(actual_out == expected_out) |
| << "Files " << settings.output_file_name << " and " << expected_output_file << " differ."; |
| } |
| |
| // TODO(https://fxbug.dev/42078677): Temporarily disable this test to facilitate a roll of |
| // rapidjson. The latest roll contains changes to rapidjson's internal `dtoa` |
| // implementation, which ever so slightly changes the string representation of |
| // certain doubles. Once the roll goes through, we should come back, change the |
| // *_expected.json files with the new slightly updated double values, and |
| // re-enable these tests. |
| TEST(ConvertTest, DISABLED_SimpleTrace) { |
| // simple_trace.fxt is a small hand-written trace file that exercises a few |
| // basic event types (currently slice begin, slice end, slice complete, async |
| // begin, and async end), and includes both inline and table referenced |
| // strings. It only contains one provider. |
| std::string test_data_path = GetTestDataPath(); |
| ConvertSettings settings; |
| settings.input_file_name = test_data_path + "simple_trace.fxt"; |
| settings.output_file_name = test_data_path + "simple_trace_actual.json"; |
| ConvertAndCompare(settings, test_data_path + "simple_trace_expected.json", kNoIgnores); |
| } |
| |
| // TODO(https://fxbug.dev/42078677): Temporarily disable this test to facilitate a roll of |
| // rapidjson. The latest roll contains changes to rapidjson's internal `dtoa` |
| // implementation, which ever so slightly changes the string representation of |
| // certain doubles. Once the roll goes through, we should come back, change the |
| // *_expected.json files with the new slightly updated double values, and |
| // re-enable these tests. |
| TEST(ConvertTest, DISABLED_ExampleBenchmark) { |
| // example_benchmark.fxt is the trace written by the program in |
| // garnet/examples/benchmark, in this case run on qemu. To collect the trace, |
| // include //src/examples/benchmark in your build and then run: |
| // ffx trace start --duration 10 --categories "benchmark" |
| // ffx component run /core/ffx-laboratory:benchmark |
| // "fuchsia-pkg://fuchsia.com/benchmark#meta/benchmark.cm" |
| |
| std::string test_data_path = GetTestDataPath(); |
| ConvertSettings settings; |
| settings.input_file_name = test_data_path + "example_benchmark.fxt"; |
| settings.output_file_name = test_data_path + "example_benchmark_actual.json"; |
| ConvertAndCompare(settings, test_data_path + "example_benchmark_expected.json", kNoIgnores); |
| } |
| |
| // TODO(https://fxbug.dev/42078677): Temporarily disable this test to facilitate a roll of |
| // rapidjson. The latest roll contains changes to rapidjson's internal `dtoa` |
| // implementation, which ever so slightly changes the string representation of |
| // certain doubles. Once the roll goes through, we should come back, change the |
| // *_expected.json files with the new slightly updated double values, and |
| // re-enable these tests. |
| TEST(ConvertTest, DISABLED_SimpleTraceCompressedOutput) { |
| // simple_trace.fxt is a small hand-written trace file that exercises a few |
| // basic event types (currently slice begin, slice end, slice complete, async |
| // begin, and async end), and includes both inline and table referenced |
| // strings. It only contains one provider. |
| std::string test_data_path = GetTestDataPath(); |
| ConvertSettings settings; |
| settings.input_file_name = test_data_path + "simple_trace.fxt"; |
| settings.output_file_name = test_data_path + "simple_trace_actual.json.gz"; |
| settings.compressed_output = true; |
| ConvertAndCompare(settings, test_data_path + "simple_trace_expected.json.gz", kIgnoreGzipOs); |
| } |
| |
| // TODO(https://fxbug.dev/42078677): Temporarily disable this test to facilitate a roll of |
| // rapidjson. The latest roll contains changes to rapidjson's internal `dtoa` |
| // implementation, which ever so slightly changes the string representation of |
| // certain doubles. Once the roll goes through, we should come back, change the |
| // *_expected.json files with the new slightly updated double values, and |
| // re-enable these tests. |
| TEST(ConvertTest, DISABLED_SimpleTraceCompressedInput) { |
| // simple_trace.fxt is a small hand-written trace file that exercises a few |
| // basic event types (currently slice begin, slice end, slice complete, async |
| // begin, and async end), and includes both inline and table referenced |
| // strings. It only contains one provider. |
| std::string test_data_path = GetTestDataPath(); |
| ConvertSettings settings; |
| settings.input_file_name = test_data_path + "simple_trace.fxt.gz"; |
| settings.output_file_name = test_data_path + "simple_trace_gz_actual.json"; |
| settings.compressed_input = true; |
| ConvertAndCompare(settings, test_data_path + "simple_trace_expected.json", kNoIgnores); |
| } |
| |
| // TODO(https://fxbug.dev/42078677): Temporarily disable this test to facilitate a roll of |
| // rapidjson. The latest roll contains changes to rapidjson's internal `dtoa` |
| // implementation, which ever so slightly changes the string representation of |
| // certain doubles. Once the roll goes through, we should come back, change the |
| // *_expected.json files with the new slightly updated double values, and |
| // re-enable these tests. |
| TEST(ConvertTest, DISABLED_SimpleTraceCompressedInputAndOutput) { |
| // simple_trace.fxt is a small hand-written trace file that exercises a few |
| // basic event types (currently slice begin, slice end, slice complete, async |
| // begin, and async end), and includes both inline and table referenced |
| // strings. It only contains one provider. |
| std::string test_data_path = GetTestDataPath(); |
| ConvertSettings settings; |
| settings.input_file_name = test_data_path + "simple_trace.fxt.gz"; |
| settings.output_file_name = test_data_path + "simple_trace_gz_actual.json.gz"; |
| settings.compressed_input = true; |
| settings.compressed_output = true; |
| ConvertAndCompare(settings, test_data_path + "simple_trace_expected.json.gz", kIgnoreGzipOs); |
| } |
| |
| TEST(ConvertTest, MissingMagicNumber) { |
| std::string test_data_path = GetTestDataPath(); |
| ConvertSettings settings; |
| settings.input_file_name = test_data_path + "no_magic.fxt"; |
| settings.output_file_name = test_data_path + "no_magic.json"; |
| EXPECT_FALSE(ConvertTrace(settings)); |
| EXPECT_FALSE(std::filesystem::exists(settings.output_file_name)); |
| } |
| |
| } // namespace |