1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2007 INRIA |
|
4 * All rights reserved. |
|
5 * |
|
6 * This program is free software; you can redistribute it and/or modify |
|
7 * it under the terms of the GNU General Public License version 2 as |
|
8 * published by the Free Software Foundation; |
|
9 * |
|
10 * This program is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 * GNU General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License |
|
16 * along with this program; if not, write to the Free Software |
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 * |
|
19 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> |
|
20 */ |
|
21 #include "composite-trace-resolver.h" |
|
22 |
|
23 namespace ns3 { |
|
24 |
|
25 CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context) |
|
26 : TraceResolver (context) |
|
27 {} |
|
28 |
|
29 CompositeTraceResolver::~CompositeTraceResolver () |
|
30 {} |
|
31 |
|
32 void |
|
33 CompositeTraceResolver::Add (std::string name, |
|
34 Callback<TraceResolver *,TraceContext const &> createResolver) |
|
35 { |
|
36 TraceContext traceContext = GetContext (); |
|
37 DoAdd (name, createResolver, traceContext); |
|
38 } |
|
39 |
|
40 void |
|
41 CompositeTraceResolver::DoAdd (std::string name, |
|
42 Callback<TraceResolver *,TraceContext const &> createResolver, |
|
43 TraceContext const &context) |
|
44 { |
|
45 struct CallbackTraceSourceItem item; |
|
46 item.name = name; |
|
47 item.createResolver = createResolver; |
|
48 item.context = context; |
|
49 m_items.push_back (item); |
|
50 } |
|
51 |
|
52 TraceResolver::TraceResolverList |
|
53 CompositeTraceResolver::DoLookup (std::string id) const |
|
54 { |
|
55 if (id == "*") |
|
56 { |
|
57 TraceResolver::TraceResolverList list; |
|
58 for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++) |
|
59 { |
|
60 list.push_back (i->createResolver (i->context)); |
|
61 } |
|
62 return list; |
|
63 } |
|
64 std::string::size_type start, end; |
|
65 start = id.find_first_of ("(", 0); |
|
66 end = id.find_first_of (")", 0); |
|
67 if (start != 0 || end != (id.size ()-1)) |
|
68 { |
|
69 for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++) |
|
70 { |
|
71 if (i->name == id) |
|
72 { |
|
73 TraceResolver::TraceResolverList list; |
|
74 list.push_back (i->createResolver (i->context)); |
|
75 return list; |
|
76 } |
|
77 } |
|
78 } |
|
79 std::list<std::string> names; |
|
80 std::string alternatives = std::string (id, start+1, end-1); |
|
81 std::string::size_type next, cur; |
|
82 next = 0; |
|
83 cur = 0; |
|
84 while (true) |
|
85 { |
|
86 std::string element; |
|
87 next = alternatives.find ("|", cur); |
|
88 if (next == std::string::npos) |
|
89 { |
|
90 element = std::string (alternatives, cur, alternatives.size ()); |
|
91 names.push_back (element); |
|
92 break; |
|
93 } |
|
94 element = std::string (alternatives, cur, next); |
|
95 names.push_back (element); |
|
96 cur = next + 1; |
|
97 } |
|
98 TraceResolver::TraceResolverList list; |
|
99 for (std::list<std::string>::const_iterator i = names.begin (); i != names.end (); i++) |
|
100 { |
|
101 for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++) |
|
102 { |
|
103 if (j->name == *i) |
|
104 { |
|
105 list.push_back (j->createResolver (j->context)); |
|
106 break; |
|
107 } |
|
108 } |
|
109 } |
|
110 return list; |
|
111 } |
|
112 |
|
113 }//namespace ns3 |
|
114 |
|
115 #ifdef RUN_SELF_TESTS |
|
116 |
|
117 #include "ns3/test.h" |
|
118 #include "trace-context-element.h" |
|
119 |
|
120 namespace ns3 { |
|
121 |
|
122 class TraceSourceTest : public TraceContextElement |
|
123 { |
|
124 public: |
|
125 enum Sources { |
|
126 DOUBLEA, |
|
127 DOUBLEB, |
|
128 SUBRESOLVER, |
|
129 }; |
|
130 static uint16_t GetUid (void) |
|
131 {static uint16_t uid = AllocateUid<TraceSourceTest> ("TraceSourceTest"); return uid;} |
|
132 void Print (std::ostream &os) |
|
133 {os << "tracesource="; |
|
134 if (m_sources == DOUBLEA) {os << "doubleA";} |
|
135 else if (m_sources == DOUBLEB) {os << "doubleB";} |
|
136 else if (m_sources == SUBRESOLVER) {os << "subresolver";} |
|
137 } |
|
138 TraceSourceTest () : m_sources (TraceSourceTest::DOUBLEA) {} |
|
139 TraceSourceTest (enum Sources sources) :m_sources (sources) {} |
|
140 bool IsDoubleA (void) {return m_sources == TraceSourceTest::DOUBLEA;} |
|
141 bool IsDoubleB (void) {return m_sources == TraceSourceTest::DOUBLEB;} |
|
142 private: |
|
143 enum TraceSourceTest::Sources m_sources; |
|
144 }; |
|
145 |
|
146 class SubTraceSourceTest : public TraceContextElement |
|
147 { |
|
148 public: |
|
149 enum Sources { |
|
150 INT, |
|
151 }; |
|
152 static uint16_t GetUid (void) |
|
153 {static uint16_t uid = AllocateUid<SubTraceSourceTest> ("SubTraceSourceTest"); return uid;} |
|
154 void Print (std::ostream &os) |
|
155 {os << "subtracesource=int";} |
|
156 SubTraceSourceTest () : m_sources (SubTraceSourceTest::INT) {} |
|
157 SubTraceSourceTest (enum Sources sources) : m_sources (sources) {} |
|
158 private: |
|
159 enum Sources m_sources; |
|
160 }; |
|
161 |
|
162 class CompositeTraceResolverTest : public Test |
|
163 { |
|
164 public: |
|
165 CompositeTraceResolverTest (); |
|
166 virtual ~CompositeTraceResolverTest (); |
|
167 virtual bool RunTests (void); |
|
168 private: |
|
169 void TraceDouble (TraceContext const &context, double v); |
|
170 void TraceInt (TraceContext const &context, int v); |
|
171 TraceResolver *CreateSubResolver (TraceContext const &context); |
|
172 |
|
173 |
|
174 bool m_gotDoubleA; |
|
175 bool m_gotDoubleB; |
|
176 CallbackTraceSource<int> m_traceInt; |
|
177 bool m_gotInt; |
|
178 }; |
|
179 |
|
180 CompositeTraceResolverTest::CompositeTraceResolverTest () |
|
181 : Test ("CompositeTraceResolver") |
|
182 {} |
|
183 CompositeTraceResolverTest::~CompositeTraceResolverTest () |
|
184 {} |
|
185 void |
|
186 CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v) |
|
187 { |
|
188 TraceSourceTest source; |
|
189 context.Get (source); |
|
190 if (source.IsDoubleA ()) |
|
191 { |
|
192 m_gotDoubleA = true; |
|
193 } |
|
194 else if (source.IsDoubleB ()) |
|
195 { |
|
196 m_gotDoubleB = true; |
|
197 } |
|
198 else |
|
199 { |
|
200 NS_FATAL_ERROR ("should not get any other trace source in this sink"); |
|
201 } |
|
202 |
|
203 } |
|
204 |
|
205 void |
|
206 CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v) |
|
207 { |
|
208 m_gotInt = true; |
|
209 } |
|
210 |
|
211 TraceResolver * |
|
212 CompositeTraceResolverTest::CreateSubResolver (TraceContext const &context) |
|
213 { |
|
214 CompositeTraceResolver *subresolver = new CompositeTraceResolver (context); |
|
215 subresolver->Add ("trace-int", m_traceInt, |
|
216 SubTraceSourceTest (SubTraceSourceTest::INT)); |
|
217 return subresolver; |
|
218 } |
|
219 bool |
|
220 CompositeTraceResolverTest::RunTests (void) |
|
221 { |
|
222 bool ok = true; |
|
223 |
|
224 CallbackTraceSource<double> traceDoubleA; |
|
225 CallbackTraceSource<double> traceDoubleB; |
|
226 TraceContext context; |
|
227 |
|
228 CompositeTraceResolver resolver (context) ; |
|
229 |
|
230 resolver.Add ("trace-double-a", traceDoubleA, |
|
231 TraceSourceTest (TraceSourceTest::DOUBLEA)); |
|
232 resolver.Add ("trace-double-b", traceDoubleB, |
|
233 TraceSourceTest (TraceSourceTest::DOUBLEB)); |
|
234 |
|
235 resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
236 |
|
237 m_gotDoubleA = false; |
|
238 m_gotDoubleB = false; |
|
239 traceDoubleA (0); |
|
240 if (!m_gotDoubleA || m_gotDoubleB) |
|
241 { |
|
242 ok = false; |
|
243 } |
|
244 m_gotDoubleA = false; |
|
245 traceDoubleA (0); |
|
246 traceDoubleB (0); |
|
247 if (!m_gotDoubleA || !m_gotDoubleB) |
|
248 { |
|
249 ok = false; |
|
250 } |
|
251 m_gotDoubleA = false; |
|
252 m_gotDoubleB = false; |
|
253 |
|
254 resolver.Disconnect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
255 |
|
256 m_gotDoubleA = false; |
|
257 m_gotDoubleB = false; |
|
258 traceDoubleA (0); |
|
259 traceDoubleB (0); |
|
260 if (m_gotDoubleA || m_gotDoubleB) |
|
261 { |
|
262 ok = false; |
|
263 } |
|
264 |
|
265 resolver.Connect ("/trace-double-a", |
|
266 MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
267 m_gotDoubleA = false; |
|
268 m_gotDoubleB = false; |
|
269 traceDoubleA (0); |
|
270 traceDoubleB (0); |
|
271 if (!m_gotDoubleA || m_gotDoubleB) |
|
272 { |
|
273 ok = false; |
|
274 } |
|
275 resolver.Disconnect ("/trace-double-a", |
|
276 MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
277 |
|
278 resolver.Connect ("/(trace-double-a)", |
|
279 MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
280 m_gotDoubleA = false; |
|
281 m_gotDoubleB = false; |
|
282 traceDoubleA (0); |
|
283 traceDoubleB (0); |
|
284 if (!m_gotDoubleA || m_gotDoubleB) |
|
285 { |
|
286 ok = false; |
|
287 } |
|
288 resolver.Disconnect ("/trace-double-a", |
|
289 MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
290 |
|
291 resolver.Connect ("/(trace-double-a|trace-double-b)", |
|
292 MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
293 m_gotDoubleA = false; |
|
294 m_gotDoubleB = false; |
|
295 traceDoubleA (0); |
|
296 traceDoubleB (0); |
|
297 if (!m_gotDoubleA || !m_gotDoubleB) |
|
298 { |
|
299 ok = false; |
|
300 } |
|
301 resolver.Disconnect ("/trace-double-a", |
|
302 MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
303 m_gotDoubleA = false; |
|
304 m_gotDoubleB = false; |
|
305 traceDoubleA (0); |
|
306 traceDoubleB (0); |
|
307 if (m_gotDoubleA || !m_gotDoubleB) |
|
308 { |
|
309 ok = false; |
|
310 } |
|
311 |
|
312 |
|
313 resolver.Disconnect ("/(trace-double-a|trace-double-b)", |
|
314 MakeCallback (&CompositeTraceResolverTest::TraceDouble, this)); |
|
315 m_gotDoubleA = false; |
|
316 m_gotDoubleB = false; |
|
317 traceDoubleA (0); |
|
318 traceDoubleB (0); |
|
319 if (m_gotDoubleA || m_gotDoubleB) |
|
320 { |
|
321 ok = false; |
|
322 } |
|
323 |
|
324 resolver.Add ("subresolver", |
|
325 MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this), |
|
326 TraceSourceTest (TraceSourceTest::SUBRESOLVER)); |
|
327 |
|
328 resolver.Connect ("/subresolver/trace-int", |
|
329 MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); |
|
330 m_gotInt = false; |
|
331 m_traceInt (1); |
|
332 if (!m_gotInt) |
|
333 { |
|
334 ok = false; |
|
335 } |
|
336 |
|
337 resolver.Disconnect ("/subresolver/trace-int", |
|
338 MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); |
|
339 m_gotInt = false; |
|
340 m_traceInt (1); |
|
341 if (m_gotInt) |
|
342 { |
|
343 ok = false; |
|
344 } |
|
345 |
|
346 resolver.Connect ("/*/trace-int", |
|
347 MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); |
|
348 m_gotInt = false; |
|
349 m_traceInt (1); |
|
350 if (!m_gotInt) |
|
351 { |
|
352 ok = false; |
|
353 } |
|
354 |
|
355 resolver.Disconnect ("/subresolver/trace-int", |
|
356 MakeCallback (&CompositeTraceResolverTest::TraceInt, this)); |
|
357 m_gotInt = false; |
|
358 m_traceInt (1); |
|
359 if (m_gotInt) |
|
360 { |
|
361 ok = false; |
|
362 } |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 return ok; |
|
368 } |
|
369 |
|
370 static CompositeTraceResolverTest g_compositeTraceResolverTest; |
|
371 |
|
372 }//namespace ns3 |
|
373 |
|
374 |
|
375 #endif /* RUN_SELF_TESTS */ |
|