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 |