1 : // Copyright 2013 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/sampler/sampled_module_cache.h"
16 :
17 : #include "base/bind.h"
18 : #include "gmock/gmock.h"
19 : #include "gtest/gtest.h"
20 :
21 : namespace sampler {
22 :
23 : struct MockedCallbackStruct {
24 E : MOCK_METHOD1(OnDeadModule, void(const SampledModuleCache::Module*));
25 : };
26 :
27 : class SampledModuleCacheTest : public ::testing::Test {
28 : public:
29 E : virtual void SetUp() override {
30 E : testing::Test::SetUp();
31 :
32 : dead_module_callback = base::Bind(&MockedCallbackStruct::OnDeadModule,
33 E : base::Unretained(&mock));
34 E : }
35 :
36 E : bool IsAlive(const SampledModuleCache::Process* process) {
37 E : return process->alive();
38 E : }
39 :
40 E : bool IsAlive(const SampledModuleCache::Module* module) {
41 E : return module->alive();
42 E : }
43 :
44 : ::testing::StrictMock<MockedCallbackStruct> mock;
45 : SampledModuleCache::DeadModuleCallback dead_module_callback;
46 : };
47 :
48 E : TEST_F(SampledModuleCacheTest, ConstructorAndProperties) {
49 E : SampledModuleCache cache(2);
50 E : EXPECT_EQ(2u, cache.log2_bucket_size());
51 :
52 E : EXPECT_TRUE(cache.dead_module_callback().is_null());
53 E : cache.set_dead_module_callback(dead_module_callback);
54 E : EXPECT_FALSE(cache.dead_module_callback().is_null());
55 E : }
56 :
57 E : TEST_F(SampledModuleCacheTest, EmptyCache) {
58 E : SampledModuleCache cache(2);
59 E : cache.RemoveDeadModules();
60 E : EXPECT_TRUE(cache.processes().empty());
61 E : }
62 :
63 E : TEST_F(SampledModuleCacheTest, EndToEnd) {
64 E : SampledModuleCache cache(2);
65 E : cache.set_dead_module_callback(dead_module_callback);
66 E : EXPECT_EQ(0u, cache.processes().size());
67 :
68 : static const DWORD kAccess =
69 : PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
70 : base::win::ScopedHandle proc(
71 E : ::OpenProcess(kAccess, FALSE, ::GetCurrentProcessId()));
72 E : ASSERT_TRUE(proc.IsValid());
73 :
74 : SampledModuleCache::ProfilingStatus status =
75 E : SampledModuleCache::kProfilingStarted;
76 E : const SampledModuleCache::Module* module = NULL;
77 :
78 : // Try to add an invalid module. This should fail.
79 E : HMODULE module_handle = ::GetModuleHandle(NULL);
80 : EXPECT_FALSE(cache.AddModule(
81 E : proc.Get(), module_handle - 1, &status, &module));
82 E : EXPECT_TRUE(module == NULL);
83 E : EXPECT_EQ(0u, cache.processes().size());
84 E : EXPECT_EQ(0u, cache.module_count());
85 :
86 : // Add this module. This should succeed.
87 E : EXPECT_TRUE(cache.AddModule(proc.Get(), module_handle, &status, &module));
88 E : EXPECT_EQ(SampledModuleCache::kProfilingStarted, status);
89 E : EXPECT_TRUE(module != NULL);
90 :
91 E : EXPECT_EQ(1u, cache.processes().size());
92 : const SampledModuleCache::Process* process =
93 E : cache.processes().begin()->second;
94 E : ASSERT_TRUE(process != NULL);
95 E : EXPECT_TRUE(IsAlive(process));
96 :
97 E : EXPECT_EQ(1u, cache.processes().begin()->second->modules().size());
98 E : const SampledModuleCache::Module* m = process->modules().begin()->second;
99 E : ASSERT_TRUE(m != NULL);
100 E : EXPECT_TRUE(IsAlive(module));
101 E : EXPECT_EQ(1u, cache.module_count());
102 E : EXPECT_EQ(module, m);
103 :
104 : // Mark the modules as dead.
105 E : cache.MarkAllModulesDead();
106 E : EXPECT_FALSE(IsAlive(process));
107 E : EXPECT_FALSE(IsAlive(module));
108 E : EXPECT_EQ(1u, cache.module_count());
109 :
110 : // Re-add the module. This should simply mark the existing module as alive.
111 E : EXPECT_TRUE(cache.AddModule(proc.Get(), module_handle, &status, &module));
112 E : EXPECT_EQ(SampledModuleCache::kProfilingContinued, status);
113 E : EXPECT_EQ(m, module);
114 :
115 E : EXPECT_EQ(1u, cache.processes().size());
116 E : EXPECT_EQ(process, cache.processes().begin()->second);
117 E : EXPECT_TRUE(IsAlive(process));
118 E : EXPECT_EQ(1u, process->modules().size());
119 E : EXPECT_EQ(module, process->modules().begin()->second);
120 E : EXPECT_TRUE(IsAlive(module));
121 E : EXPECT_EQ(1u, cache.module_count());
122 :
123 : // Clean up the modules. Nothing should be removed and the callback should
124 : // not be invoked.
125 E : cache.RemoveDeadModules();
126 E : EXPECT_EQ(1u, cache.processes().size());
127 E : EXPECT_EQ(process, cache.processes().begin()->second);
128 E : EXPECT_TRUE(IsAlive(process));
129 E : EXPECT_EQ(1u, process->modules().size());
130 E : EXPECT_EQ(module, process->modules().begin()->second);
131 E : EXPECT_TRUE(IsAlive(module));
132 E : EXPECT_EQ(1u, cache.module_count());
133 :
134 E : EXPECT_CALL(mock, OnDeadModule(module)).Times(1);
135 :
136 : // Mark everything as dead and clean up the modules. The callback should be
137 : // invoked and the cache should now be empty.
138 E : cache.MarkAllModulesDead();
139 E : cache.RemoveDeadModules();
140 E : EXPECT_EQ(0u, cache.processes().size());
141 E : EXPECT_EQ(0u, cache.module_count());
142 E : }
143 :
144 : } // namespace sampler
|