1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/asan/asan_logger.h"
16 :
17 : #include <string>
18 :
19 : #include "base/bind.h"
20 : #include "base/bind_helpers.h"
21 : #include "base/environment.h"
22 : #include "base/file_util.h"
23 : #include "base/string_util.h"
24 : #include "base/stringprintf.h"
25 : #include "base/utf_string_conversions.h"
26 : #include "base/files/file_path.h"
27 : #include "base/files/scoped_temp_dir.h"
28 : #include "base/memory/scoped_ptr.h"
29 : #include "gmock/gmock.h"
30 : #include "gtest/gtest.h"
31 : #include "syzygy/agent/asan/asan_runtime.h"
32 : #include "syzygy/trace/logger/logger.h"
33 : #include "syzygy/trace/logger/logger_rpc_impl.h"
34 : #include "syzygy/trace/protocol/call_trace_defs.h"
35 :
36 : namespace agent {
37 : namespace asan {
38 :
39 : namespace {
40 :
41 : using testing::Return;
42 :
43 : class TestAsanLogger : public AsanLogger {
44 : public:
45 : using AsanLogger::instance_id_;
46 : using AsanLogger::rpc_binding_;
47 : };
48 :
49 : class AsanLoggerTest : public testing::Test {
50 : public:
51 E : AsanLoggerTest() {
52 E : EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
53 E : temp_path_ = temp_dir_.path().Append(L"log.txt");
54 :
55 : // Setup the instance id.
56 E : instance_id_ = base::StringPrintf(L"%d", ::GetCurrentProcessId());
57 E : }
58 :
59 E : MOCK_METHOD1(LoggerStoppedCallback, bool(trace::common::Service*));
60 :
61 : protected:
62 : base::ScopedTempDir temp_dir_;
63 : base::FilePath temp_path_;
64 : std::wstring instance_id_;
65 : TestAsanLogger client_;
66 : };
67 :
68 : } // namespace
69 :
70 E : TEST_F(AsanLoggerTest, EndToEnd) {
71 E : const std::string kMessage("This is the test message\n");
72 :
73 : {
74 : // Setup a log file destination.
75 E : file_util::ScopedFILE destination(file_util::OpenFile(temp_path_, "wb"));
76 :
77 : // Start up the logging service.
78 E : trace::logger::Logger server;
79 E : trace::logger::RpcLoggerInstanceManager instance_manager(&server);
80 E : server.set_instance_id(instance_id_);
81 E : server.set_destination(destination.get());
82 E : server.set_minidump_dir(temp_dir_.path());
83 E : ASSERT_TRUE(server.Start());
84 :
85 : // Use the AsanLogger client.
86 E : client_.set_instance_id(instance_id_);
87 E : client_.set_log_as_text(true);
88 E : client_.set_minidump_on_failure(true);
89 E : client_.Init();
90 E : ASSERT_EQ(instance_id_, client_.instance_id_);
91 E : ASSERT_TRUE(client_.rpc_binding_.Get() != NULL);
92 E : client_.Write(kMessage);
93 :
94 : // Generate a minidump.
95 E : CONTEXT ctx = {};
96 E : ::RtlCaptureContext(&ctx);
97 E : AsanErrorInfo info = {};
98 E : client_.SaveMiniDump(&ctx, &info);
99 :
100 : // Shutdown the logging service.
101 E : ASSERT_TRUE(server.Stop());
102 E : ASSERT_TRUE(server.Join());
103 E : }
104 :
105 : // Inspect the log file contents.
106 E : std::string content;
107 E : ASSERT_TRUE(file_util::ReadFileToString(temp_path_, &content));
108 E : ASSERT_THAT(content, testing::EndsWith(kMessage));
109 :
110 : // We should have exactly one minidump in the temp directory.
111 : using file_util::FileEnumerator;
112 E : FileEnumerator fe(temp_dir_.path(), false, FileEnumerator::FILES, L"*.dmp");
113 E : base::FilePath minidump(fe.Next());
114 E : EXPECT_FALSE(minidump.empty());
115 E : EXPECT_TRUE(fe.Next().empty());
116 :
117 : // TODO(rogerm): Inspect the contents of the minidump.
118 E : }
119 :
120 E : TEST_F(AsanLoggerTest, Stop) {
121 : // Setup a log file destination.
122 E : file_util::ScopedFILE destination(file_util::OpenFile(temp_path_, "wb"));
123 :
124 : // Start up the logging service.
125 E : trace::logger::Logger server;
126 E : trace::logger::RpcLoggerInstanceManager instance_manager(&server);
127 E : server.set_instance_id(instance_id_);
128 E : server.set_destination(destination.get());
129 : server.set_stopped_callback(
130 : base::Bind(&AsanLoggerTest::LoggerStoppedCallback,
131 E : base::Unretained(this)));
132 E : ASSERT_TRUE(server.Start());
133 :
134 : // Use the AsanLogger client.
135 E : client_.set_instance_id(instance_id_);
136 E : client_.Init();
137 E : ASSERT_EQ(instance_id_, client_.instance_id_);
138 E : ASSERT_TRUE(client_.rpc_binding_.Get() != NULL);
139 :
140 : trace::common::Service* server_base = static_cast<trace::common::Service*>(
141 E : &server);
142 : EXPECT_CALL(*this, LoggerStoppedCallback(server_base)).Times(1).
143 E : WillOnce(Return(true));
144 E : client_.Stop();
145 E : ASSERT_TRUE(server.Join());
146 E : }
147 :
148 : } // namespace asan
149 : } // namespace agent
|