1 : // Copyright 2015 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/bard/story.h"
16 :
17 : #include "gtest/gtest.h"
18 : #include "syzygy/bard/events/heap_alloc_event.h"
19 : #include "syzygy/bard/events/heap_create_event.h"
20 : #include "syzygy/bard/events/heap_destroy_event.h"
21 : #include "syzygy/bard/events/heap_free_event.h"
22 : #include "syzygy/bard/events/heap_size_event.h"
23 : #include "syzygy/bard/events/linked_event.h"
24 : #include "syzygy/core/unittest_util.h"
25 :
26 : namespace bard {
27 : namespace {
28 :
29 : using events::LinkedEvent;
30 :
31 : using events::HeapAllocEvent;
32 : using events::HeapCreateEvent;
33 : using events::HeapDestroyEvent;
34 : using events::HeapFreeEvent;
35 : using events::HeapSizeEvent;
36 :
37 : const HANDLE kLiveHeap = reinterpret_cast<HANDLE>(0x4197FC83);
38 : const HANDLE kTraceHeap = reinterpret_cast<HANDLE>(0xAB12CD34);
39 : const LPVOID kLiveAlloc = reinterpret_cast<LPVOID>(0x4820BC7A);
40 : const LPVOID kTraceAlloc = reinterpret_cast<LPVOID>(0xF1D97AE4);
41 : const DWORD kFlags = 1;
42 : const DWORD kOptions = 0;
43 : const SIZE_T kBytes = 100;
44 : const SIZE_T kSize = 100;
45 : const SIZE_T kInitialSize = 1;
46 : const SIZE_T kMaximumSize = 1000;
47 :
48 : class InvalidEvent : public EventInterface {
49 : public:
50 : EventType type() const override { return EventType::kMaxEventType; }
51 :
52 : bool Play(void* backdrop) override { return true; }
53 : bool Equals(const EventInterface*) const override { return false; }
54 : };
55 :
56 : } // namespace
57 :
58 : // Comparison operator. This is out of the anonymous namespace so it can be
59 : // found by the unittest helper.
60 E : bool operator==(const Story::PlotLine& pl1, const Story::PlotLine& pl2) {
61 E : if (pl1.size() != pl2.size())
62 i : return false;
63 E : for (size_t i = 0; i < pl1.size(); ++i) {
64 E : if (!pl1[i]->Equals(pl2[i]))
65 i : return false;
66 E : }
67 E : return true;
68 E : }
69 :
70 : // Comparison operator. This is out of the anonymous namespace so it can be
71 : // found by the unittest helper.
72 E : bool operator==(const Story& s1, const Story& s2) {
73 E : if (s1.plot_lines().size() != s2.plot_lines().size())
74 i : return false;
75 E : for (size_t i = 0; i < s1.plot_lines().size(); ++i) {
76 E : if (!(*s1.plot_lines()[i] == *s2.plot_lines()[i]))
77 i : return false;
78 E : }
79 E : return true;
80 E : }
81 :
82 E : TEST(StoryTest, CreatePlotLine) {
83 E : Story s;
84 E : EXPECT_EQ(0u, s.plot_lines().size());
85 E : auto pl = s.CreatePlotLine();
86 E : EXPECT_TRUE(pl);
87 E : EXPECT_EQ(1u, s.plot_lines().size());
88 :
89 E : Story::PlotLine* pl2 = new Story::PlotLine();
90 E : EXPECT_EQ(pl2, s.AddPlotLine(scoped_ptr<Story::PlotLine>(pl2)));
91 E : EXPECT_EQ(2u, s.plot_lines().size());
92 E : }
93 :
94 E : TEST(StoryTest, TestSerialization) {
95 : scoped_ptr<EventInterface> event1(
96 E : new HeapCreateEvent(kOptions, kInitialSize, kMaximumSize, kTraceHeap));
97 : scoped_ptr<EventInterface> event2(
98 E : new HeapAllocEvent(kTraceHeap, kFlags, kBytes, kTraceAlloc));
99 : scoped_ptr<EventInterface> event3(
100 E : new HeapSizeEvent(kTraceHeap, kFlags, kTraceAlloc, kSize));
101 : scoped_ptr<EventInterface> event4(
102 E : new HeapFreeEvent(kTraceHeap, kFlags, kTraceAlloc, true));
103 E : scoped_ptr<EventInterface> event5(new HeapDestroyEvent(kTraceHeap, true));
104 :
105 : // The following events will either be cross plot line dependencies or have
106 : // such dependencies.
107 E : scoped_ptr<LinkedEvent> linked_event1(new LinkedEvent(event1.Pass()));
108 E : scoped_ptr<LinkedEvent> linked_event2(new LinkedEvent(event2.Pass()));
109 E : scoped_ptr<LinkedEvent> linked_event4(new LinkedEvent(event4.Pass()));
110 E : scoped_ptr<LinkedEvent> linked_event5(new LinkedEvent(event5.Pass()));
111 :
112 : // Alloc depends on Create, as it would be on another thread.
113 E : linked_event2->AddDep(linked_event1.get());
114 :
115 : // Similarly the heap can't be detroyed until all use of it has been
116 : // completed.
117 E : linked_event5->AddDep(linked_event4.get());
118 :
119 E : scoped_ptr<Story::PlotLine> plot_line1(new Story::PlotLine());
120 E : scoped_ptr<Story::PlotLine> plot_line2(new Story::PlotLine());
121 :
122 : // One plot line creates and frees the heap.
123 E : plot_line1->push_back(linked_event1.Pass());
124 E : plot_line1->push_back(linked_event5.Pass());
125 :
126 : // Another plot line owns the allocation.
127 E : plot_line2->push_back(linked_event2.Pass());
128 E : plot_line2->push_back(event3.Pass());
129 E : plot_line2->push_back(linked_event4.Pass());
130 :
131 : // Create a story to wrap it all up.
132 E : Story story;
133 E : story.AddPlotLine(plot_line1.Pass());
134 E : story.AddPlotLine(plot_line2.Pass());
135 :
136 E : EXPECT_TRUE(testing::TestSerialization(story));
137 E : }
138 :
139 : } // namespace bard
|