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/qname.h" 15#include "webrtc/libjingle/xmllite/xmlparser.h" 16#include "webrtc/base/common.h" 17#include "webrtc/base/gunit.h" 18 19using buzz::QName; 20using buzz::XmlParser; 21using buzz::XmlParseContext; 22using buzz::XmlParseHandler; 23 24class XmlParserTestHandler : public XmlParseHandler { 25 public: 26 virtual void StartElement(XmlParseContext * pctx, 27 const char * name, const char ** atts) { 28 ss_ << "START (" << pctx->ResolveQName(name, false).Merged(); 29 while (*atts) { 30 ss_ << ", " << pctx->ResolveQName(*atts, true).Merged() 31 << "='" << *(atts+1) << "'"; 32 atts += 2; 33 } 34 ss_ << ") "; 35 } 36 virtual void EndElement(XmlParseContext * pctx, const char * name) { 37 RTC_UNUSED(pctx); 38 RTC_UNUSED(name); 39 ss_ << "END "; 40 } 41 virtual void CharacterData(XmlParseContext * pctx, 42 const char * text, int len) { 43 RTC_UNUSED(pctx); 44 ss_ << "TEXT (" << std::string(text, len) << ") "; 45 } 46 virtual void Error(XmlParseContext * pctx, XML_Error code) { 47 RTC_UNUSED(pctx); 48 ss_ << "ERROR (" << static_cast<int>(code) << ") "; 49 } 50 virtual ~XmlParserTestHandler() { 51 } 52 53 std::string Str() { 54 return ss_.str(); 55 } 56 57 std::string StrClear() { 58 std::string result = ss_.str(); 59 ss_.str(""); 60 return result; 61 } 62 63 private: 64 std::stringstream ss_; 65}; 66 67 68TEST(XmlParserTest, TestTrivial) { 69 XmlParserTestHandler handler; 70 XmlParser::ParseXml(&handler, "<testing/>"); 71 EXPECT_EQ("START (testing) END ", handler.Str()); 72} 73 74TEST(XmlParserTest, TestAttributes) { 75 { 76 XmlParserTestHandler handler; 77 XmlParser::ParseXml(&handler, "<testing a='b'/>"); 78 EXPECT_EQ("START (testing, a='b') END ", handler.Str()); 79 } 80 { 81 XmlParserTestHandler handler; 82 XmlParser::ParseXml(&handler, "<testing e='' long='some text'/>"); 83 EXPECT_EQ("START (testing, e='', long='some text') END ", handler.Str()); 84 } 85} 86 87TEST(XmlParserTest, TestNesting) { 88 { 89 XmlParserTestHandler handler; 90 XmlParser::ParseXml(&handler, 91 "<top><first/><second><third></third></second></top>"); 92 EXPECT_EQ("START (top) START (first) END START (second) START (third) " 93 "END END END ", handler.Str()); 94 } 95 { 96 XmlParserTestHandler handler; 97 XmlParser::ParseXml(&handler, "<top><fifth><deeper><and><deeper/></and>" 98 "<sibling><leaf/></sibling></deeper></fifth><first/><second>" 99 "<third></third></second></top>"); 100 EXPECT_EQ("START (top) START (fifth) START (deeper) START (and) START " 101 "(deeper) END END START (sibling) START (leaf) END END END " 102 "END START (first) END START (second) START (third) END END END ", 103 handler.Str()); 104 } 105} 106 107TEST(XmlParserTest, TestXmlDecl) { 108 { 109 XmlParserTestHandler handler; 110 XmlParser::ParseXml(&handler, "<?xml version=\"1.0\"?><testing/>"); 111 EXPECT_EQ("START (testing) END ", handler.Str()); 112 } 113 { 114 XmlParserTestHandler handler; 115 XmlParser::ParseXml(&handler, 116 "<?xml version=\"1.0\" encoding=\"utf-8\"?><testing/>"); 117 EXPECT_EQ("START (testing) END ", handler.Str()); 118 } 119 { 120 XmlParserTestHandler handler; 121 XmlParser::ParseXml(&handler, 122 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" 123 "<testing/>"); 124 EXPECT_EQ("START (testing) END ", handler.Str()); 125 } 126} 127 128TEST(XmlParserTest, TestNamespace) { 129 { 130 XmlParserTestHandler handler; 131 XmlParser::ParseXml(&handler, "<top xmlns='my-namespace' a='b'/>"); 132 EXPECT_EQ("START (my-namespace:top, xmlns='my-namespace', a='b') END ", 133 handler.Str()); 134 } 135 { 136 XmlParserTestHandler handler; 137 XmlParser::ParseXml(&handler, "<foo:top xmlns:foo='my-namespace' " 138 "a='b' foo:c='d'/>"); 139 EXPECT_EQ("START (my-namespace:top, " 140 "http://www.w3.org/2000/xmlns/:foo='my-namespace', " 141 "a='b', my-namespace:c='d') END ", handler.Str()); 142 } 143 { 144 XmlParserTestHandler handler; 145 XmlParser::ParseXml(&handler, "<top><nested xmlns='my-namespace'><leaf/>" 146 "</nested><sibling/></top>"); 147 EXPECT_EQ("START (top) START (my-namespace:nested, xmlns='my-namespace') " 148 "START (my-namespace:leaf) END END START (sibling) END END ", 149 handler.Str()); 150 } 151} 152 153TEST(XmlParserTest, TestIncremental) { 154 XmlParserTestHandler handler; 155 XmlParser parser(&handler); 156 std::string fragment; 157 158 fragment = "<stream:stream"; 159 parser.Parse(fragment.c_str(), fragment.length(), false); 160 EXPECT_EQ("", handler.StrClear()); 161 162 fragment = " id=\"abcdefg\" xmlns=\""; 163 parser.Parse(fragment.c_str(), fragment.length(), false); 164 EXPECT_EQ("", handler.StrClear()); 165 166 fragment = "j:c\" xmlns:stream='hm"; 167 parser.Parse(fragment.c_str(), fragment.length(), false); 168 EXPECT_EQ("", handler.StrClear()); 169 170 fragment = "ph'><test"; 171 parser.Parse(fragment.c_str(), fragment.length(), false); 172 EXPECT_EQ("START (hmph:stream, id='abcdefg', xmlns='j:c', " 173 "http://www.w3.org/2000/xmlns/:stream='hmph') ", handler.StrClear()); 174 175 fragment = "ing/><again/>abracad"; 176 parser.Parse(fragment.c_str(), fragment.length(), false); 177 EXPECT_EQ("START (j:c:testing) END START (j:c:again) END TEXT (abracad) ", 178 handler.StrClear()); 179 180 fragment = "abra</stream:"; 181 parser.Parse(fragment.c_str(), fragment.length(), false); 182 EXPECT_EQ("TEXT (abra) ", handler.StrClear()); 183 184 fragment = "stream>"; 185 parser.Parse(fragment.c_str(), fragment.length(), false); 186 EXPECT_EQ("END ", handler.StrClear()); 187} 188 189TEST(XmlParserTest, TestReset) { 190 { 191 XmlParserTestHandler handler; 192 XmlParser parser(&handler); 193 std::string fragment; 194 195 fragment = "<top><first/><second><third></third>"; 196 parser.Parse(fragment.c_str(), fragment.length(), false); 197 EXPECT_EQ("START (top) START (first) END START (second) START (third) END ", 198 handler.StrClear()); 199 200 parser.Reset(); 201 fragment = "<tip><first/><second><third></third>"; 202 parser.Parse(fragment.c_str(), fragment.length(), false); 203 EXPECT_EQ("START (tip) START (first) END START (second) START (third) END ", 204 handler.StrClear()); 205 } 206 { 207 XmlParserTestHandler handler; 208 XmlParser parser(&handler); 209 std::string fragment; 210 211 fragment = "<top xmlns='m'>"; 212 parser.Parse(fragment.c_str(), fragment.length(), false); 213 EXPECT_EQ("START (m:top, xmlns='m') ", handler.StrClear()); 214 215 fragment = "<testing/><frag"; 216 parser.Parse(fragment.c_str(), fragment.length(), false); 217 EXPECT_EQ("START (m:testing) END ", handler.StrClear()); 218 219 parser.Reset(); 220 fragment = "<testing><fragment/"; 221 parser.Parse(fragment.c_str(), fragment.length(), false); 222 EXPECT_EQ("START (testing) ", handler.StrClear()); 223 224 fragment = ">"; 225 parser.Parse(fragment.c_str(), fragment.length(), false); 226 EXPECT_EQ("START (fragment) END ", handler.StrClear()); 227 } 228} 229 230TEST(XmlParserTest, TestError) { 231 { 232 XmlParserTestHandler handler; 233 XmlParser::ParseXml(&handler, "junk"); 234 EXPECT_EQ("ERROR (2) ", handler.Str()); 235 } 236 { 237 XmlParserTestHandler handler; 238 XmlParser::ParseXml(&handler, "<top/> garbage "); 239 EXPECT_EQ("START (top) END ERROR (9) ", handler.Str()); 240 } 241 { 242 XmlParserTestHandler handler; 243 XmlParser::ParseXml(&handler, "<-hm->"); 244 EXPECT_EQ("ERROR (4) ", handler.Str()); 245 } 246 { 247 XmlParserTestHandler handler; 248 XmlParser::ParseXml(&handler, "<hello>&foobar;</hello>"); 249 EXPECT_EQ("START (hello) ERROR (11) ", handler.Str()); 250 } 251 { 252 XmlParserTestHandler handler; 253 XmlParser::ParseXml(&handler, 254 "<!DOCTYPE HTML PUBLIC \"foobar\" \"barfoo\">"); 255 EXPECT_EQ("ERROR (3) ", handler.Str()); 256 } 257 { 258 // XmlParser requires utf-8 259 XmlParserTestHandler handler; 260 XmlParser::ParseXml(&handler, 261 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><test/>"); 262 EXPECT_EQ("ERROR (19) ", handler.Str()); 263 } 264 { 265 // XmlParser requires version 1.0 266 XmlParserTestHandler handler; 267 XmlParser::ParseXml(&handler, 268 "<?xml version=\"2.0\"?><test/>"); 269 EXPECT_EQ("ERROR (2) ", handler.Str()); 270 } 271 { 272 // XmlParser requires standalone documents 273 XmlParserTestHandler handler; 274 XmlParser::ParseXml(&handler, 275 "<?xml version=\"1.0\" standalone=\"no\"?><test/>"); 276 EXPECT_EQ("ERROR (2) ", handler.Str()); 277 } 278 { 279 // XmlParser doesn't like empty namespace URIs 280 XmlParserTestHandler handler; 281 XmlParser::ParseXml(&handler, 282 "<test xmlns:foo='' foo:bar='huh?'>"); 283 EXPECT_EQ("ERROR (2) ", handler.Str()); 284 } 285} 286