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/files/file_enumerator.h"
24 : #include "base/files/file_path.h"
25 : #include "base/files/scoped_temp_dir.h"
26 : #include "base/memory/scoped_ptr.h"
27 : #include "base/strings/string_util.h"
28 : #include "base/strings/stringprintf.h"
29 : #include "base/strings/utf_string_conversions.h"
30 : #include "gmock/gmock.h"
31 : #include "gtest/gtest.h"
32 : #include "syzygy/agent/asan/asan_runtime.h"
33 : #include "syzygy/trace/agent_logger/agent_logger.h"
34 : #include "syzygy/trace/agent_logger/agent_logger_rpc_impl.h"
35 : #include "syzygy/trace/protocol/call_trace_defs.h"
36 :
37 : namespace agent {
38 : namespace asan {
39 :
40 : namespace {
41 :
42 : using testing::Return;
43 :
44 : class TestAsanLogger : public AsanLogger {
45 : public:
46 : using AsanLogger::instance_id_;
47 : using AsanLogger::rpc_binding_;
48 : };
49 :
50 : class AsanLoggerTest : public testing::Test {
51 : public:
52 E : AsanLoggerTest() {
53 E : EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
54 E : temp_path_ = temp_dir_.path().Append(L"log.txt");
55 :
56 : // Setup the instance id.
57 E : instance_id_ = base::StringPrintf(L"%d", ::GetCurrentProcessId());
58 E : }
59 :
60 E : MOCK_METHOD1(LoggerStoppedCallback, bool(trace::common::Service*));
61 :
62 : protected:
63 : base::ScopedTempDir temp_dir_;
64 : base::FilePath temp_path_;
65 : std::wstring instance_id_;
66 : TestAsanLogger client_;
67 : };
68 :
69 : } // namespace
70 :
71 E : TEST_F(AsanLoggerTest, EndToEnd) {
72 E : const std::string kMessage("This is the test message\n");
73 :
74 : {
75 : // Setup a log file destination.
76 E : base::ScopedFILE destination(base::OpenFile(temp_path_, "wb"));
77 :
78 : // Start up the logging service.
79 E : trace::agent_logger::AgentLogger server;
80 E : trace::agent_logger::RpcLoggerInstanceManager instance_manager(&server);
81 E : server.set_instance_id(instance_id_);
82 E : server.set_destination(destination.get());
83 E : server.set_minidump_dir(temp_dir_.path());
84 E : ASSERT_TRUE(server.Start());
85 :
86 : // Use the AsanLogger client.
87 E : client_.set_instance_id(instance_id_);
88 E : client_.set_log_as_text(true);
89 E : client_.set_minidump_on_failure(true);
90 E : client_.Init();
91 E : ASSERT_EQ(instance_id_, client_.instance_id_);
92 E : ASSERT_TRUE(client_.rpc_binding_.Get() != NULL);
93 :
94 : // Generate a minidump.
95 E : CONTEXT ctx = {};
96 E : ::RtlCaptureContext(&ctx);
97 E : AsanErrorInfo info = {};
98 E : client_.SaveMiniDump(&ctx, &info);
99 E : client_.Write(kMessage);
100 :
101 : // Shutdown the logging service.
102 E : ASSERT_TRUE(server.Stop());
103 E : ASSERT_TRUE(server.Join());
104 E : }
105 :
106 : // Inspect the log file contents.
107 E : std::string content;
108 E : ASSERT_TRUE(base::ReadFileToString(temp_path_, &content));
109 E : ASSERT_THAT(content, testing::EndsWith(kMessage));
110 :
111 : // We should have exactly one minidump in the temp directory.
112 : using base::FileEnumerator;
113 E : FileEnumerator fe(temp_dir_.path(), false, FileEnumerator::FILES, L"*.dmp");
114 E : base::FilePath minidump(fe.Next());
115 E : EXPECT_FALSE(minidump.empty());
116 E : EXPECT_TRUE(fe.Next().empty());
117 :
118 : // TODO(rogerm): Inspect the contents of the minidump.
119 E : }
120 :
121 E : TEST_F(AsanLoggerTest, Stop) {
122 : // Setup a log file destination.
123 E : base::ScopedFILE destination(base::OpenFile(temp_path_, "wb"));
124 :
125 : // Start up the logging service.
126 E : trace::agent_logger::AgentLogger server;
127 E : trace::agent_logger::RpcLoggerInstanceManager instance_manager(&server);
128 E : server.set_instance_id(instance_id_);
129 E : server.set_destination(destination.get());
130 : server.set_stopped_callback(
131 : base::Bind(&AsanLoggerTest::LoggerStoppedCallback,
132 E : base::Unretained(this)));
133 E : ASSERT_TRUE(server.Start());
134 :
135 : // Use the AsanLogger client.
136 E : client_.set_instance_id(instance_id_);
137 E : client_.Init();
138 E : ASSERT_EQ(instance_id_, client_.instance_id_);
139 E : ASSERT_TRUE(client_.rpc_binding_.Get() != NULL);
140 :
141 : trace::common::Service* server_base = static_cast<trace::common::Service*>(
142 E : &server);
143 : EXPECT_CALL(*this, LoggerStoppedCallback(server_base)).Times(1).
144 E : WillOnce(Return(true));
145 E : client_.Stop();
146 E : ASSERT_TRUE(server.Join());
147 E : }
148 :
149 : } // namespace asan
150 : } // namespace agent
|