OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <iostream> | |
12 #include <sstream> | |
13 #include <string> | |
14 #include "webrtc/libjingle/xmllite/xmlelement.h" | |
15 #include "webrtc/base/common.h" | |
16 #include "webrtc/base/gunit.h" | |
17 #include "webrtc/base/thread.h" | |
18 | |
19 using buzz::QName; | |
20 using buzz::XmlAttr; | |
21 using buzz::XmlChild; | |
22 using buzz::XmlElement; | |
23 | |
24 std::ostream& operator<<(std::ostream& os, const QName& name) { | |
25 os << name.Namespace() << ":" << name.LocalPart(); | |
26 return os; | |
27 } | |
28 | |
29 TEST(XmlElementTest, TestConstructors) { | |
30 XmlElement elt(QName("google:test", "first")); | |
31 EXPECT_EQ("<test:first xmlns:test=\"google:test\"/>", elt.Str()); | |
32 | |
33 XmlElement elt2(QName("google:test", "first"), true); | |
34 EXPECT_EQ("<first xmlns=\"google:test\"/>", elt2.Str()); | |
35 } | |
36 | |
37 TEST(XmlElementTest, TestAdd) { | |
38 XmlElement elt(QName("google:test", "root"), true); | |
39 elt.AddElement(new XmlElement(QName("google:test", "first"))); | |
40 elt.AddElement(new XmlElement(QName("google:test", "nested")), 1); | |
41 elt.AddText("nested-value", 2); | |
42 elt.AddText("between-", 1); | |
43 elt.AddText("value", 1); | |
44 elt.AddElement(new XmlElement(QName("google:test", "nested2")), 1); | |
45 elt.AddElement(new XmlElement(QName("google:test", "second"))); | |
46 elt.AddText("init-value", 1); | |
47 elt.AddElement(new XmlElement(QName("google:test", "nested3")), 1); | |
48 elt.AddText("trailing-value", 1); | |
49 | |
50 // make sure it looks ok overall | |
51 EXPECT_EQ("<root xmlns=\"google:test\">" | |
52 "<first><nested>nested-value</nested>between-value<nested2/></first>" | |
53 "<second>init-value<nested3/>trailing-value</second></root>", | |
54 elt.Str()); | |
55 | |
56 // make sure text was concatenated | |
57 XmlChild * pchild = | |
58 elt.FirstChild()->AsElement()->FirstChild()->NextChild(); | |
59 EXPECT_TRUE(pchild->IsText()); | |
60 EXPECT_EQ("between-value", pchild->AsText()->Text()); | |
61 } | |
62 | |
63 TEST(XmlElementTest, TestAttrs) { | |
64 XmlElement elt(QName("", "root")); | |
65 elt.SetAttr(QName("", "a"), "avalue"); | |
66 EXPECT_EQ("<root a=\"avalue\"/>", elt.Str()); | |
67 | |
68 elt.SetAttr(QName("", "b"), "bvalue"); | |
69 EXPECT_EQ("<root a=\"avalue\" b=\"bvalue\"/>", elt.Str()); | |
70 | |
71 elt.SetAttr(QName("", "a"), "avalue2"); | |
72 EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue\"/>", elt.Str()); | |
73 | |
74 elt.SetAttr(QName("", "b"), "bvalue2"); | |
75 EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\"/>", elt.Str()); | |
76 | |
77 elt.SetAttr(QName("", "c"), "cvalue"); | |
78 EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\" c=\"cvalue\"/>", elt.Str()); | |
79 | |
80 XmlAttr * patt = elt.FirstAttr(); | |
81 EXPECT_EQ(QName("", "a"), patt->Name()); | |
82 EXPECT_EQ("avalue2", patt->Value()); | |
83 | |
84 patt = patt->NextAttr(); | |
85 EXPECT_EQ(QName("", "b"), patt->Name()); | |
86 EXPECT_EQ("bvalue2", patt->Value()); | |
87 | |
88 patt = patt->NextAttr(); | |
89 EXPECT_EQ(QName("", "c"), patt->Name()); | |
90 EXPECT_EQ("cvalue", patt->Value()); | |
91 | |
92 patt = patt->NextAttr(); | |
93 EXPECT_TRUE(NULL == patt); | |
94 | |
95 EXPECT_TRUE(elt.HasAttr(QName("", "a"))); | |
96 EXPECT_TRUE(elt.HasAttr(QName("", "b"))); | |
97 EXPECT_TRUE(elt.HasAttr(QName("", "c"))); | |
98 EXPECT_FALSE(elt.HasAttr(QName("", "d"))); | |
99 | |
100 elt.SetAttr(QName("", "d"), "dvalue"); | |
101 EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\" c=\"cvalue\" d=\"dvalue\"/>", | |
102 elt.Str()); | |
103 EXPECT_TRUE(elt.HasAttr(QName("", "d"))); | |
104 | |
105 elt.ClearAttr(QName("", "z")); // not found, no effect | |
106 EXPECT_EQ("<root a=\"avalue2\" b=\"bvalue2\" c=\"cvalue\" d=\"dvalue\"/>", | |
107 elt.Str()); | |
108 | |
109 elt.ClearAttr(QName("", "b")); | |
110 EXPECT_EQ("<root a=\"avalue2\" c=\"cvalue\" d=\"dvalue\"/>", elt.Str()); | |
111 | |
112 elt.ClearAttr(QName("", "a")); | |
113 EXPECT_EQ("<root c=\"cvalue\" d=\"dvalue\"/>", elt.Str()); | |
114 | |
115 elt.ClearAttr(QName("", "d")); | |
116 EXPECT_EQ("<root c=\"cvalue\"/>", elt.Str()); | |
117 | |
118 elt.ClearAttr(QName("", "c")); | |
119 EXPECT_EQ("<root/>", elt.Str()); | |
120 } | |
121 | |
122 TEST(XmlElementTest, TestBodyText) { | |
123 XmlElement elt(QName("", "root")); | |
124 EXPECT_EQ("", elt.BodyText()); | |
125 | |
126 elt.AddText("body value text"); | |
127 | |
128 EXPECT_EQ("body value text", elt.BodyText()); | |
129 | |
130 elt.ClearChildren(); | |
131 elt.AddText("more value "); | |
132 elt.AddText("text"); | |
133 | |
134 EXPECT_EQ("more value text", elt.BodyText()); | |
135 | |
136 elt.ClearChildren(); | |
137 elt.AddText("decoy"); | |
138 elt.AddElement(new XmlElement(QName("", "dummy"))); | |
139 EXPECT_EQ("", elt.BodyText()); | |
140 | |
141 elt.SetBodyText("replacement"); | |
142 EXPECT_EQ("replacement", elt.BodyText()); | |
143 | |
144 elt.SetBodyText(""); | |
145 EXPECT_TRUE(NULL == elt.FirstChild()); | |
146 | |
147 elt.SetBodyText("goodbye"); | |
148 EXPECT_EQ("goodbye", elt.FirstChild()->AsText()->Text()); | |
149 EXPECT_EQ("goodbye", elt.BodyText()); | |
150 } | |
151 | |
152 TEST(XmlElementTest, TestCopyConstructor) { | |
153 XmlElement * element = XmlElement::ForStr( | |
154 "<root xmlns='test-foo'>This is a <em a='avalue' b='bvalue'>" | |
155 "little <b>little</b></em> test</root>"); | |
156 | |
157 XmlElement * pelCopy = new XmlElement(*element); | |
158 EXPECT_EQ("<root xmlns=\"test-foo\">This is a <em a=\"avalue\" b=\"bvalue\">" | |
159 "little <b>little</b></em> test</root>", pelCopy->Str()); | |
160 delete pelCopy; | |
161 | |
162 pelCopy = new XmlElement(*(element->FirstChild()->NextChild()->AsElement())); | |
163 EXPECT_EQ("<foo:em a=\"avalue\" b=\"bvalue\" xmlns:foo=\"test-foo\">" | |
164 "little <foo:b>little</foo:b></foo:em>", pelCopy->Str()); | |
165 | |
166 XmlAttr * patt = pelCopy->FirstAttr(); | |
167 EXPECT_EQ(QName("", "a"), patt->Name()); | |
168 EXPECT_EQ("avalue", patt->Value()); | |
169 | |
170 patt = patt->NextAttr(); | |
171 EXPECT_EQ(QName("", "b"), patt->Name()); | |
172 EXPECT_EQ("bvalue", patt->Value()); | |
173 | |
174 patt = patt->NextAttr(); | |
175 EXPECT_TRUE(NULL == patt); | |
176 delete pelCopy; | |
177 delete element; | |
178 } | |
179 | |
180 TEST(XmlElementTest, TestNameSearch) { | |
181 XmlElement * element = XmlElement::ForStr( | |
182 "<root xmlns='test-foo'>" | |
183 "<firstname>George</firstname>" | |
184 "<middlename>X.</middlename>" | |
185 "some text" | |
186 "<lastname>Harrison</lastname>" | |
187 "<firstname>John</firstname>" | |
188 "<middlename>Y.</middlename>" | |
189 "<lastname>Lennon</lastname>" | |
190 "</root>"); | |
191 EXPECT_TRUE(NULL == | |
192 element->FirstNamed(QName("", "firstname"))); | |
193 EXPECT_EQ(element->FirstChild(), | |
194 element->FirstNamed(QName("test-foo", "firstname"))); | |
195 EXPECT_EQ(element->FirstChild()->NextChild(), | |
196 element->FirstNamed(QName("test-foo", "middlename"))); | |
197 EXPECT_EQ(element->FirstElement()->NextElement(), | |
198 element->FirstNamed(QName("test-foo", "middlename"))); | |
199 EXPECT_EQ("Harrison", | |
200 element->TextNamed(QName("test-foo", "lastname"))); | |
201 EXPECT_EQ(element->FirstElement()->NextElement()->NextElement(), | |
202 element->FirstNamed(QName("test-foo", "lastname"))); | |
203 EXPECT_EQ("John", element->FirstNamed(QName("test-foo", "firstname"))-> | |
204 NextNamed(QName("test-foo", "firstname"))->BodyText()); | |
205 EXPECT_EQ("Y.", element->FirstNamed(QName("test-foo", "middlename"))-> | |
206 NextNamed(QName("test-foo", "middlename"))->BodyText()); | |
207 EXPECT_EQ("Lennon", element->FirstNamed(QName("test-foo", "lastname"))-> | |
208 NextNamed(QName("test-foo", "lastname"))->BodyText()); | |
209 EXPECT_TRUE(NULL == element->FirstNamed(QName("test-foo", "firstname"))-> | |
210 NextNamed(QName("test-foo", "firstname"))-> | |
211 NextNamed(QName("test-foo", "firstname"))); | |
212 | |
213 delete element; | |
214 } | |
215 | |
216 class XmlElementCreatorThread : public rtc::Thread { | |
217 public: | |
218 XmlElementCreatorThread(int count, buzz::QName qname) : | |
219 count_(count), qname_(qname) {} | |
220 | |
221 virtual ~XmlElementCreatorThread() { | |
222 Stop(); | |
223 } | |
224 | |
225 virtual void Run() { | |
226 std::vector<buzz::XmlElement*> elems; | |
227 for (int i = 0; i < count_; i++) { | |
228 elems.push_back(new XmlElement(qname_)); | |
229 } | |
230 for (int i = 0; i < count_; i++) { | |
231 delete elems[i]; | |
232 } | |
233 } | |
234 | |
235 private: | |
236 int count_; | |
237 buzz::QName qname_; | |
238 }; | |
239 | |
240 // If XmlElement creation and destruction isn't thread safe, | |
241 // this test should crash. | |
242 TEST(XmlElementTest, TestMultithread) { | |
243 int thread_count = 2; // Was 100, but that's too slow. | |
244 int elem_count = 100; // Was 100000, but that's too slow. | |
245 buzz::QName qname("foo", "bar"); | |
246 | |
247 std::vector<rtc::Thread*> threads; | |
248 for (int i = 0; i < thread_count; i++) { | |
249 threads.push_back( | |
250 new XmlElementCreatorThread(elem_count, qname)); | |
251 threads[i]->Start(); | |
252 } | |
253 | |
254 for (int i = 0; i < thread_count; i++) { | |
255 threads[i]->Stop(); | |
256 delete threads[i]; | |
257 } | |
258 } | |
OLD | NEW |