| // Copyright 2012 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "syzygy/grinder/grinder_app.h" |
| |
| #include "base/scoped_temp_dir.h" |
| #include "gtest/gtest.h" |
| #include "syzygy/common/application.h" |
| #include "syzygy/core/unittest_util.h" |
| #include "syzygy/pe/unittest_util.h" |
| |
| namespace grinder { |
| |
| namespace { |
| |
| class TestGrinderApp : public GrinderApp { |
| public: |
| // Expose for testing. |
| using GrinderApp::trace_files_; |
| using GrinderApp::output_file_; |
| }; |
| |
| class GrinderAppTest : public testing::PELibUnitTest { |
| public: |
| typedef testing::PELibUnitTest Super; |
| typedef common::Application<TestGrinderApp> TestApplication; |
| |
| GrinderAppTest() |
| : cmd_line_(FilePath(L"grinder.exe")), |
| impl_(app_.implementation()) { |
| } |
| |
| virtual void SetUp() OVERRIDE { |
| Super::SetUp(); |
| |
| // Setup the IO streams. |
| ASSERT_NO_FATAL_FAILURE(CreateTemporaryDir(&temp_dir_)); |
| stdin_path_ = temp_dir_.Append(L"NUL"); |
| stdout_path_ = temp_dir_.Append(L"stdout.txt"); |
| stderr_path_ = temp_dir_.Append(L"stderr.txt"); |
| ASSERT_NO_FATAL_FAILURE(InitStreams( |
| stdin_path_, stdout_path_, stderr_path_)); |
| |
| // Point the application at the test's command-line and IO streams. |
| app_.set_command_line(&cmd_line_); |
| app_.set_in(in()); |
| app_.set_out(out()); |
| app_.set_err(err()); |
| } |
| |
| protected: |
| // The command line to be given to the application under test. |
| CommandLine cmd_line_; |
| |
| // The application object under test. |
| TestApplication app_; |
| |
| // A reference to the underlying application implementation for convenience. |
| TestGrinderApp& impl_; |
| |
| // A temporary folder where all IO will be stored. |
| FilePath temp_dir_; |
| |
| // @name File paths used for the standard IO streams. |
| // @{ |
| FilePath stdin_path_; |
| FilePath stdout_path_; |
| FilePath stderr_path_; |
| // @} |
| }; |
| |
| } // namespace |
| |
| TEST_F(GrinderAppTest, ParseCommandLineFailsWithNoMode) { |
| cmd_line_.AppendArgPath(FilePath(L"foo.dat")); |
| ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_)); |
| } |
| |
| TEST_F(GrinderAppTest, ParseCommandLineFailsWithNoFiles) { |
| cmd_line_.AppendSwitchASCII("mode", "profile"); |
| ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_)); |
| } |
| |
| TEST_F(GrinderAppTest, ParseCommandLineTraceFiles) { |
| std::vector<FilePath> temp_files; |
| cmd_line_.AppendSwitchASCII("mode", "profile"); |
| for (size_t i = 0; i < 10; ++i) { |
| FilePath temp_file; |
| ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_, &temp_file)); |
| cmd_line_.AppendArgPath(temp_file); |
| temp_files.push_back(temp_file); |
| } |
| |
| ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_)); |
| ASSERT_EQ(temp_files, impl_.trace_files_); |
| } |
| |
| TEST_F(GrinderAppTest, ParseCommandLineOutputFile) { |
| ASSERT_TRUE(impl_.output_file_.empty()); |
| cmd_line_.AppendSwitchASCII("mode", "profile"); |
| cmd_line_.AppendSwitchPath("output-file", FilePath(L"output.txt")); |
| cmd_line_.AppendArgPath( |
| testing::GetExeTestDataRelativePath(L"profile_traces/trace-1.bin")); |
| |
| ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_)); |
| ASSERT_EQ(L"output.txt", impl_.output_file_.value()); |
| } |
| |
| TEST_F(GrinderAppTest, BasicBlockEntryEndToEnd) { |
| cmd_line_.AppendSwitchASCII("mode", "bbentry"); |
| cmd_line_.AppendArgPath( |
| testing::GetExeTestDataRelativePath( |
| L"basic_block_entry_traces/trace-1.bin")); |
| |
| FilePath output_file; |
| ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_, &output_file)); |
| ASSERT_TRUE(file_util::Delete(output_file, false)); |
| cmd_line_.AppendSwitchPath("output-file", output_file); |
| |
| ASSERT_TRUE(!file_util::PathExists(output_file)); |
| |
| EXPECT_EQ(0, app_.Run()); |
| |
| // Verify that the output file was created. |
| EXPECT_TRUE(file_util::PathExists(output_file)); |
| } |
| |
| TEST_F(GrinderAppTest, ProfileEndToEnd) { |
| cmd_line_.AppendSwitchASCII("mode", "profile"); |
| cmd_line_.AppendArgPath( |
| testing::GetExeTestDataRelativePath(L"profile_traces/trace-1.bin")); |
| |
| FilePath output_file; |
| ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_, &output_file)); |
| ASSERT_TRUE(file_util::Delete(output_file, false)); |
| cmd_line_.AppendSwitchPath("output-file", output_file); |
| |
| ASSERT_TRUE(!file_util::PathExists(output_file)); |
| |
| EXPECT_EQ(0, app_.Run()); |
| |
| // Verify that the output file was created. |
| EXPECT_TRUE(file_util::PathExists(output_file)); |
| } |
| |
| TEST_F(GrinderAppTest, CoverageEndToEnd) { |
| cmd_line_.AppendSwitchASCII("mode", "coverage"); |
| cmd_line_.AppendArgPath( |
| testing::GetExeTestDataRelativePath(L"coverage_traces/trace-1.bin")); |
| |
| FilePath output_file; |
| ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_, &output_file)); |
| ASSERT_TRUE(file_util::Delete(output_file, false)); |
| cmd_line_.AppendSwitchPath("output-file", output_file); |
| cmd_line_.AppendSwitchASCII("output-format", "lcov"); |
| |
| ASSERT_TRUE(!file_util::PathExists(output_file)); |
| |
| EXPECT_EQ(0, app_.Run()); |
| |
| // Verify that the output file was created. |
| EXPECT_TRUE(file_util::PathExists(output_file)); |
| } |
| |
| } // namespace grinder |