1 //
2 // Copyright 2018 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24
25 #include "pxr/base/trace/trace.h"
26 #include "pxr/base/trace/collectionNotice.h"
27 #include "pxr/base/trace/serialization.h"
28
29 #include <fstream>
30 #include <iostream>
31 #include <sstream>
32
33 PXR_NAMESPACE_USING_DIRECTIVE
34
35 // Declare a custom Trace category
36 constexpr TraceCategoryId TestCategory
37 = TraceCategory::CreateTraceCategoryId("TestCategory");
38
39 static std::unique_ptr<TraceEventList>
CreateTestEvents(TraceEvent::TimeStamp timeStampOffset)40 CreateTestEvents(TraceEvent::TimeStamp timeStampOffset)
41 {
42 const TraceEvent::TimeStamp ms = ArchSecondsToTicks(0.001);
43 timeStampOffset += ms;
44 std::unique_ptr<TraceEventList> events(new TraceEventList);
45
46 static constexpr TraceStaticKeyData counterKey("Test Counter");
47 {
48 TraceEvent counterEvent(
49 TraceEvent::CounterDelta,
50 counterKey,
51 1,
52 TraceCategory::Default
53 );
54 counterEvent.SetTimeStamp(2*ms + timeStampOffset);
55 events->EmplaceBack(std::move(counterEvent));
56 }
57
58 events->EmplaceBack(
59 TraceEvent::Begin,
60 events->CacheKey("Inner Scope 2"),
61 3*ms + timeStampOffset,
62 TestCategory
63 );
64 events->EmplaceBack(
65 TraceEvent::End,
66 events->CacheKey("Inner Scope 2"),
67 4*ms + timeStampOffset,
68 TestCategory
69 );
70
71 {
72 bool data = true;
73 TraceEvent dataEvent(
74 TraceEvent::Data,
75 events->CacheKey("Test Data 0"),
76 data,
77 TraceCategory::Default
78 );
79 dataEvent.SetTimeStamp(5*ms+timeStampOffset);
80 events->EmplaceBack(std::move(dataEvent));
81 }
82 {
83 int data = -2;
84 TraceEvent dataEvent(
85 TraceEvent::Data,
86 events->CacheKey("Test Data 1"),
87 data,
88 TraceCategory::Default
89 );
90 dataEvent.SetTimeStamp(6*ms+timeStampOffset);
91 events->EmplaceBack(std::move(dataEvent));
92 }
93 {
94 uint64_t data = ~0;
95 TraceEvent dataEvent(
96 TraceEvent::Data,
97 events->CacheKey("Test Data 2"),
98 data,
99 TraceCategory::Default
100 );
101 dataEvent.SetTimeStamp(7*ms+timeStampOffset);
102 events->EmplaceBack(std::move(dataEvent));
103 }
104 {
105 double data = 1.5;
106 TraceEvent dataEvent(
107 TraceEvent::Data,
108 events->CacheKey("Test Data 3"),
109 data,
110 TraceCategory::Default
111 );
112 dataEvent.SetTimeStamp(8*ms+timeStampOffset);
113 events->EmplaceBack(std::move(dataEvent));
114 }
115 {
116 std::string data = "String Data";
117 TraceEvent dataEvent(
118 TraceEvent::Data,
119 events->CacheKey("Test Data 4"),
120 events->StoreData(data.c_str()),
121 TraceCategory::Default
122 );
123 dataEvent.SetTimeStamp(9*ms+timeStampOffset);
124 events->EmplaceBack(std::move(dataEvent));
125 }
126
127 static constexpr TraceStaticKeyData keyInner("InnerScope");
128 events->EmplaceBack(TraceEvent::Timespan, keyInner,
129 ms + timeStampOffset,
130 10*ms + timeStampOffset,
131 TraceCategory::Default);
132
133
134 {
135 TraceEvent counterEvent(
136 TraceEvent::CounterDelta,
137 counterKey,
138 1,
139 TraceCategory::Default
140 );
141 counterEvent.SetTimeStamp(11*ms + timeStampOffset);
142 events->EmplaceBack(std::move(counterEvent));
143 }
144 {
145 TraceEvent counterEvent(
146 TraceEvent::CounterValue,
147 counterKey,
148 -1,
149 TraceCategory::Default
150 );
151 counterEvent.SetTimeStamp(12*ms + timeStampOffset);
152 events->EmplaceBack(std::move(counterEvent));
153 }
154 static constexpr TraceStaticKeyData keyOuter("OuterScope");
155 events->EmplaceBack(TraceEvent::Timespan, keyOuter,
156 0 + timeStampOffset,
157 13*ms + timeStampOffset,
158 TraceCategory::Default);
159
160 events->EmplaceBack(
161 TraceEvent::Marker,
162 events->CacheKey("Test Marker 1"),
163 4*ms + timeStampOffset,
164 TraceCategory::Default
165 );
166
167 events->EmplaceBack(
168 TraceEvent::Marker,
169 events->CacheKey("Test Marker 2"),
170 5*ms + timeStampOffset,
171 TraceCategory::Default
172 );
173 return events;
174 }
175
176 static std::unique_ptr<TraceCollection>
CreateTestCollection(float startTimeSec=0.0)177 CreateTestCollection(float startTimeSec=0.0)
178 {
179 std::unique_ptr<TraceCollection> collection(new TraceCollection);
180 collection->AddToCollection(
181 TraceThreadId("Thread 1"),
182 CreateTestEvents(ArchSecondsToTicks(startTimeSec)));
183 collection->AddToCollection(TraceThreadId("Thread 2"),
184 CreateTestEvents(ArchSecondsToTicks(startTimeSec + 0.001)));
185 return collection;
186 }
187
188 static void
_TestSerialization(const std::vector<std::shared_ptr<TraceCollection>> & testCols,std::string fileName)189 _TestSerialization(
190 const std::vector<std::shared_ptr<TraceCollection>>& testCols,
191 std::string fileName)
192 {
193 std::stringstream test;
194 bool written = false;
195 if (testCols.size() == 1 ) {
196 written = TraceSerialization::Write(test, testCols[0]);
197 } else {
198 written = TraceSerialization::Write(test, testCols);
199 }
200 TF_AXIOM(written);
201
202 // Write out the file
203 {
204 std::ofstream ostream(fileName);
205 ostream << test.str();
206 }
207 // Read a collection from the file just written
208 std::shared_ptr<TraceCollection> collection;
209 {
210 std::ifstream istream(fileName);
211 collection = TraceSerialization::Read(istream);
212 TF_AXIOM(collection);
213 }
214
215 std::string stringRepr = test.str();
216
217 std::stringstream test2;
218 bool written2 = TraceSerialization::Write(test2, collection);
219 TF_AXIOM(written2);
220
221 std::string stringRepr2 = test2.str();
222
223 // This comparison might be too strict.
224 if (stringRepr != stringRepr2) {
225 std::cout << "Written:\n" << stringRepr << "\n";
226 std::cout << "Reconstruction:\n" << stringRepr2 << "\n";
227 }
228 TF_AXIOM(stringRepr == stringRepr2);
229 }
230
231 int
main(int argc,char * argv[])232 main(int argc, char *argv[])
233 {
234 TraceCategory::GetInstance().RegisterCategory(
235 TestCategory, "Test Category");
236
237 std::vector<std::shared_ptr<TraceCollection>> collections;
238 std::cout << "Testing single collection\n";
239 collections.emplace_back(CreateTestCollection());
240 _TestSerialization(collections, "trace.json");
241 std::cout << " PASSED\n";
242
243 std::cout << "Testing multiple collections\n";
244 collections.emplace_back(CreateTestCollection(20.0/1000.0));
245 _TestSerialization(collections, "trace2.json");
246 std::cout << " PASSED\n";
247 }
248