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