1 // Copyright 2008, Google Inc. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 // This file contains the unit tests for the internal Attributes class.
27
28 #include "kml/base/attributes.h"
29 #include <algorithm>
30 #include "boost/scoped_ptr.hpp"
31 #include "gtest/gtest.h"
32
33 namespace kmlbase {
34
35 static const char kAttr0[] = "id";
36 static const char kAttr1[] = "fraction";
37 static const char kAttr2[] = "xunits";
38 static const char kNoSuchAttr[] = "no-such-attr";
39
40 class AttributesTest : public testing::Test {
41 protected:
SetUp()42 virtual void SetUp() {
43 attributes_.reset(new Attributes);
44 }
45 boost::scoped_ptr<Attributes> attributes_;
46 };
47
TEST_F(AttributesTest,TestCreate)48 TEST_F(AttributesTest, TestCreate) {
49 // A list of name-value pairs as expat might produce.
50 const char* atts[] = {
51 "name",
52 "Placemark",
53 "type",
54 "kml:PlacemarkType",
55 "substitutionGroup",
56 "kml:AbstractFeatureGroup",
57 NULL
58 };
59 // Call the method under test.
60 attributes_.reset(Attributes::Create(atts));
61 ASSERT_TRUE(attributes_.get());
62 string got_val;
63 ASSERT_TRUE(attributes_->GetValue(atts[0], &got_val));
64 ASSERT_EQ(string(atts[1]), got_val);
65 ASSERT_TRUE(attributes_->GetValue(atts[2], &got_val));
66 ASSERT_EQ(string(atts[3]), got_val);
67 ASSERT_TRUE(attributes_->GetValue(atts[4], &got_val));
68 ASSERT_EQ(string(atts[5]), got_val);
69 ASSERT_FALSE(attributes_->GetValue("no-such-attr", &got_val));
70 // Verify null output is well behaved.
71 string* p = NULL;
72 ASSERT_TRUE(attributes_->GetValue(atts[0], p));
73 ASSERT_FALSE(attributes_->GetValue("no-such_attr", p));
74 }
75
TEST_F(AttributesTest,TestCreateOdd)76 TEST_F(AttributesTest, TestCreateOdd) {
77 // A bad atts list.
78 const char* atts[] = { "a0", "a1", "b0", 0 };
79 // Call the method under test.
80 attributes_.reset(Attributes::Create(atts));
81 ASSERT_TRUE(attributes_.get());
82 string got_val;
83 ASSERT_TRUE(attributes_->GetValue(atts[0], &got_val));
84 ASSERT_EQ(string(atts[1]), got_val);
85 ASSERT_FALSE(attributes_->GetValue(atts[2], &got_val));
86 }
87
TEST_F(AttributesTest,TestGetStringDesctructive)88 TEST_F(AttributesTest, TestGetStringDesctructive) {
89 const char* atts[] = { "id", "placemark-123", "unknown", "somevalue", 0 };
90 attributes_.reset(Attributes::Create(atts));
91 string got_val;
92 ASSERT_TRUE(attributes_->GetValue(atts[0], &got_val));
93 string got_val_again;
94 const string kAtt0(atts[0]);
95 ASSERT_TRUE(attributes_->CutValue(kAtt0, &got_val_again));
96 ASSERT_FALSE(attributes_->GetValue(atts[0], &got_val_again));
97 }
98
TEST_F(AttributesTest,TestSetGetString)99 TEST_F(AttributesTest, TestSetGetString) {
100 const string kVal0 = "val0";
101 const string kVal1 = "val1";
102 attributes_->SetValue(kAttr0, kVal0);
103 attributes_->SetValue(kAttr1, kVal1);
104 string got_val;
105 ASSERT_TRUE(attributes_->GetValue(kAttr0, &got_val));
106 ASSERT_EQ(kVal0, got_val);
107 ASSERT_TRUE(attributes_->GetValue(kAttr1, &got_val));
108 ASSERT_EQ(kVal1, got_val);
109 ASSERT_TRUE(false == attributes_->GetValue(kNoSuchAttr, &got_val));
110 ASSERT_EQ(kVal1, got_val);
111 }
112
TEST_F(AttributesTest,TestSetGetDouble)113 TEST_F(AttributesTest, TestSetGetDouble) {
114 const double kVal0 = 123.456;
115 const double kVal1 = 987.654321;
116 attributes_->SetValue(kAttr0, kVal0);
117 attributes_->SetValue(kAttr1, kVal1);
118 double got_val;
119 ASSERT_TRUE(attributes_->GetValue(kAttr0, &got_val));
120 ASSERT_EQ(kVal0, got_val);
121 ASSERT_TRUE(attributes_->GetValue(kAttr1, &got_val));
122 ASSERT_EQ(kVal1, got_val);
123 ASSERT_TRUE(false == attributes_->GetValue(kNoSuchAttr, &got_val));
124 ASSERT_EQ(kVal1, got_val);
125 }
126
TEST_F(AttributesTest,TestSetGetInt)127 TEST_F(AttributesTest, TestSetGetInt) {
128 const int kVal0 = 123;
129 const int kVal1 = -987;
130 attributes_->SetValue(kAttr0, kVal0);
131 attributes_->SetValue(kAttr1, kVal1);
132 int got_val;
133 ASSERT_TRUE(attributes_->GetValue(kAttr0, &got_val));
134 ASSERT_EQ(kVal0, got_val);
135 ASSERT_TRUE(attributes_->GetValue(kAttr1, &got_val));
136 ASSERT_EQ(kVal1, got_val);
137 ASSERT_TRUE(false == attributes_->GetValue(kNoSuchAttr, &got_val));
138 ASSERT_EQ(kVal1, got_val);
139 }
140
TEST_F(AttributesTest,TestClone)141 TEST_F(AttributesTest, TestClone) {
142 const string kVal0 = "val0";
143 const double kVal1 = 123.456789;
144 attributes_->SetValue(kAttr0, kVal0);
145 attributes_->SetValue(kAttr1, kVal1);
146 Attributes* clone = attributes_->Clone();
147 string got_string;
148 EXPECT_TRUE(clone->GetValue(kAttr0, &got_string));
149 EXPECT_EQ(kVal0, got_string);
150
151 double got_double;
152 EXPECT_TRUE(clone->GetValue(kAttr1, &got_double));
153 EXPECT_EQ(kVal1, got_double);
154
155 delete clone;
156 clone = NULL;
157 }
158
TEST_F(AttributesTest,TestMerge)159 TEST_F(AttributesTest, TestMerge) {
160 const string kVal0 = "val0";
161 const double kVal1a = 123.456789;
162 const double kVal1b = 78.90123;
163 const string kVal2 = "fraction";
164 attributes_->SetValue(kAttr0, kVal0);
165 attributes_->SetValue(kAttr1, kVal1a);
166 Attributes attributes;
167 attributes.SetValue(kAttr1, kVal1b);
168 attributes.SetValue(kAttr2, kVal2);
169 attributes_->MergeAttributes(attributes);
170 string got_string;
171 ASSERT_TRUE(attributes_->GetValue(kAttr0, &got_string));
172 ASSERT_EQ(kVal0, got_string);
173 double got_double;
174 ASSERT_TRUE(attributes_->GetValue(kAttr1, &got_double));
175 ASSERT_EQ(kVal1b, got_double);
176 ASSERT_TRUE(attributes_->GetValue(kAttr2, &got_string));
177 ASSERT_EQ(kVal2, got_string);
178 }
179
TEST_F(AttributesTest,TestSerialize)180 TEST_F(AttributesTest, TestSerialize) {
181 const string kVal0 = "val0";
182 const double kVal1 = 123.456789;
183 attributes_->SetValue(kAttr0, kVal0);
184 attributes_->SetValue(kAttr1, kVal1);
185 string serialized;
186 attributes_->Serialize(&serialized);
187 const string expecting = " " + string(kAttr1) + "=\"123.456789\" "
188 + string(kAttr0) + "=\"" + kVal0 + "\"";
189 ASSERT_EQ(expecting, serialized);
190 }
191
TEST_F(AttributesTest,TestSplit)192 TEST_F(AttributesTest, TestSplit) {
193 // <kml xmlns="http://www.opengis.net/kml/2.2"
194 // xmlns:ex="http://vendor.com/kml/2.2ext">
195 // Expat turns the above XML into this:
196 const char* atts[] = {
197 "xmlns", "http://www.opengis.net/kml/2.2",
198 "xmlns:ex", "http://vendor.com/kml/2.2ext",
199 NULL
200 };
201 attributes_.reset(Attributes::Create(atts));
202 ASSERT_TRUE(attributes_.get());
203 // This is the method under test.
204 boost::scoped_ptr<Attributes> xmlns_(attributes_->SplitByPrefix("xmlns"));
205 ASSERT_TRUE(xmlns_.get());
206 ASSERT_EQ(static_cast<size_t>(1), xmlns_->GetSize());
207 string val;
208 ASSERT_TRUE(xmlns_->GetValue("ex", &val));
209 ASSERT_EQ(string(atts[3]), val);
210 }
211
TEST_F(AttributesTest,TestMatchNoDefault)212 TEST_F(AttributesTest, TestMatchNoDefault) {
213 const char* atts[] = {
214 "xmlns:kml", "http://www.opengis.net/kml/2.2",
215 "xmlns:ex", "http://vendor.com/kml/2.2ext",
216 NULL
217 };
218 attributes_.reset(Attributes::Create(atts));
219 ASSERT_TRUE(attributes_.get());
220 // This is the method under test.
221 boost::scoped_ptr<Attributes> xmlns_(attributes_->SplitByPrefix("xmlns"));
222 ASSERT_TRUE(xmlns_.get());
223 ASSERT_EQ(static_cast<size_t>(2), xmlns_->GetSize());
224 string val;
225 ASSERT_TRUE(xmlns_->GetValue("kml", &val));
226 ASSERT_EQ(string(atts[1]), val);
227 ASSERT_TRUE(xmlns_->GetValue("ex", &val));
228 ASSERT_EQ(string(atts[3]), val);
229 }
230
TEST_F(AttributesTest,TestGetAttrNames)231 TEST_F(AttributesTest, TestGetAttrNames) {
232 // A list of name-value pairs as expat might produce.
233 const char* atts[] = {
234 "name",
235 "Placemark",
236 "type",
237 "kml:PlacemarkType",
238 "substitutionGroup",
239 "kml:AbstractFeatureGroup",
240 NULL
241 };
242 attributes_.reset(Attributes::Create(atts));
243 std::vector<string> attr_names;
244 attributes_->GetAttrNames(&attr_names);
245 ASSERT_EQ(static_cast<size_t>(3), attr_names.size());
246 ASSERT_FALSE(attr_names.end() ==
247 std::find(attr_names.begin(), attr_names.end(), "name"));
248 ASSERT_FALSE(attr_names.end() ==
249 std::find(attr_names.begin(), attr_names.end(), "type"));
250 ASSERT_FALSE(attr_names.end() == std::find(attr_names.begin(),
251 attr_names.end(),
252 "substitutionGroup"));
253 }
254
TEST_F(AttributesTest,TestIterator)255 TEST_F(AttributesTest, TestIterator) {
256 // NOTE: the keys are in map order.
257 const char* atts[] = { "a", "z", "b", "y", "c", "x", NULL };
258 attributes_.reset(Attributes::Create(atts));
259 ASSERT_TRUE(attributes_.get());
260 StringMapIterator iter = attributes_->CreateIterator();
261 ASSERT_EQ(string(atts[0]), iter.Data().first);
262 ASSERT_EQ(string(atts[1]), iter.Data().second);
263 iter.Advance();
264 ASSERT_FALSE(iter.AtEnd());
265 ASSERT_EQ(string(atts[2]), iter.Data().first);
266 ASSERT_EQ(string(atts[3]), iter.Data().second);
267 iter.Advance();
268 ASSERT_FALSE(iter.AtEnd());
269 ASSERT_EQ(string(atts[4]), iter.Data().first);
270 ASSERT_EQ(string(atts[5]), iter.Data().second);
271 iter.Advance();
272 ASSERT_TRUE(iter.AtEnd());
273 }
274
275 } // end namespace kmlbase
276