PageRenderTime 55ms CodeModel.GetById 10ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/test/llsdutil_tut.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 389 lines | 289 code | 39 blank | 61 comment | 20 complexity | 78398669443f6f025b9dc48c34adfac6 MD5 | raw file
  1/**
  2 * @file llsdutil_tut.cpp
  3 * @author Adroit
  4 * @date 2007-02
  5 * @brief LLSD conversion routines test cases.
  6 *
  7 * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29#include "linden_common.h"
 30#include "lltut.h"
 31#include "m4math.h"
 32#include "v2math.h"
 33#include "v2math.h"
 34#include "v3color.h"
 35#include "v3math.h"
 36#include "v3dmath.h"
 37#include "v4coloru.h"
 38#include "v4math.h"
 39#include "llquaternion.h"
 40#include "llsdutil.h"
 41#include "llsdutil_math.h"
 42#include "stringize.h"
 43#include <set>
 44#include <boost/range.hpp>
 45
 46namespace tut
 47{
 48	struct llsdutil_data
 49	{
 50        void test_matches(const std::string& proto_key, const LLSD& possibles,
 51                          const char** begin, const char** end)
 52        {
 53            std::set<std::string> succeed(begin, end);
 54            LLSD prototype(possibles[proto_key]);
 55            for (LLSD::map_const_iterator pi(possibles.beginMap()), pend(possibles.endMap());
 56                 pi != pend; ++pi)
 57            {
 58                std::string match(llsd_matches(prototype, pi->second));
 59                std::set<std::string>::const_iterator found = succeed.find(pi->first);
 60                if (found != succeed.end())
 61                {
 62                    // This test is supposed to succeed. Comparing to the
 63                    // empty string ensures that if the test fails, it will
 64                    // display the string received so we can tell what failed.
 65                    ensure_equals("match", match, "");
 66                }
 67                else
 68                {
 69                    // This test is supposed to fail. If we get a false match,
 70                    // the string 'match' will be empty, which doesn't tell us
 71                    // much about which case went awry. So construct a more
 72                    // detailed description string.
 73                    ensure(proto_key + " shouldn't match " + pi->first, ! match.empty());
 74                }
 75            }
 76        }
 77	};
 78	typedef test_group<llsdutil_data> llsdutil_test;;
 79	typedef llsdutil_test::object llsdutil_object;
 80	tut::llsdutil_test tutil("llsdutil");
 81
 82	template<> template<>
 83	void llsdutil_object::test<1>()
 84	{
 85		LLSD sd;
 86		U64 valueIn , valueOut;
 87		valueIn = U64L(0xFEDCBA9876543210);
 88		sd = ll_sd_from_U64(valueIn);
 89		valueOut = ll_U64_from_sd(sd);
 90		ensure_equals("U64 valueIn->sd->valueOut", valueIn, valueOut);
 91	}
 92
 93	template<> template<>
 94	void llsdutil_object::test<2>()
 95	{
 96		LLSD sd;
 97		U32 valueIn, valueOut;
 98		valueIn = 0x87654321;
 99		sd = ll_sd_from_U32(valueIn);
100		valueOut = ll_U32_from_sd(sd);
101		ensure_equals("U32 valueIn->sd->valueOut", valueIn, valueOut);
102	}
103
104	template<> template<>
105	void llsdutil_object::test<3>()
106	{
107		U32 valueIn, valueOut;
108		valueIn = 0x87654321;
109		LLSD sd;
110		sd = ll_sd_from_ipaddr(valueIn);
111		valueOut = ll_ipaddr_from_sd(sd);
112		ensure_equals("valueIn->sd->valueOut", valueIn, valueOut);
113	}
114
115	template<> template<>
116	void llsdutil_object::test<4>()
117	{
118		LLSD sd;
119		LLVector3 vec1(-1.0, 2.0, -3.0);
120		sd = ll_sd_from_vector3(vec1); 
121		LLVector3 vec2 = ll_vector3_from_sd(sd);
122		ensure_equals("vector3 -> sd -> vector3: 1", vec1, vec2);
123
124		LLVector3 vec3(sd);
125		ensure_equals("vector3 -> sd -> vector3: 2", vec1, vec3);
126
127		sd.clear();
128		vec1.setVec(0., 0., 0.);
129		sd = ll_sd_from_vector3(vec1); 
130		vec2 = ll_vector3_from_sd(sd);
131		ensure_equals("vector3 -> sd -> vector3: 3", vec1, vec2);
132		sd.clear();
133	}
134
135	template<> template<>
136	void llsdutil_object::test<5>()
137	{
138		LLSD sd;
139		LLVector3d vec1((F64)(U64L(0xFEDCBA9876543210) << 2), -1., 0);
140		sd = ll_sd_from_vector3d(vec1); 
141		LLVector3d vec2 = ll_vector3d_from_sd(sd);
142		ensure_equals("vector3d -> sd -> vector3d: 1", vec1, vec2);
143		
144		LLVector3d vec3(sd); 
145		ensure_equals("vector3d -> sd -> vector3d : 2", vec1, vec3);
146	}
147
148	template<> template<>
149	void llsdutil_object::test<6>()
150	{
151		LLSD sd;
152		LLVector2 vec((F32) -3., (F32) 4.2);
153		sd = ll_sd_from_vector2(vec); 
154		LLVector2 vec1 = ll_vector2_from_sd(sd);
155		ensure_equals("vector2 -> sd -> vector2", vec, vec1);
156		
157		LLSD sd2 = ll_sd_from_vector2(vec1); 
158		ensure_equals("sd -> vector2 -> sd: 2", sd, sd2);
159	}
160
161	template<> template<>
162	void llsdutil_object::test<7>()
163	{
164		LLSD sd;
165		LLQuaternion quat((F32) 1., (F32) -0.98, (F32) 2.3, (F32) 0xffff);
166		sd = ll_sd_from_quaternion(quat); 
167		LLQuaternion quat1 = ll_quaternion_from_sd(sd);
168		ensure_equals("LLQuaternion -> sd -> LLQuaternion", quat, quat1);
169		
170		LLSD sd2 = ll_sd_from_quaternion(quat1); 
171		ensure_equals("sd -> LLQuaternion -> sd ", sd, sd2);
172	}
173
174	template<> template<>
175	void llsdutil_object::test<8>()
176	{
177		LLSD sd;
178		LLColor4 c(1.0f, 2.2f, 4.0f, 7.f);
179		sd = ll_sd_from_color4(c); 
180		LLColor4 c1 =ll_color4_from_sd(sd);
181		ensure_equals("LLColor4 -> sd -> LLColor4", c, c1);
182		
183		LLSD sd1 = ll_sd_from_color4(c1);
184		ensure_equals("sd -> LLColor4 -> sd", sd, sd1);
185	}
186
187    template<> template<>
188    void llsdutil_object::test<9>()
189    {
190        set_test_name("llsd_matches");
191
192        // for this test, construct a map of all possible LLSD types
193        LLSD map;
194        map.insert("empty",     LLSD());
195        map.insert("Boolean",   LLSD::Boolean());
196        map.insert("Integer",   LLSD::Integer(0));
197        map.insert("Real",      LLSD::Real(0.0));
198        map.insert("String",    LLSD::String("bah"));
199        map.insert("NumString", LLSD::String("1"));
200        map.insert("UUID",      LLSD::UUID());
201        map.insert("Date",      LLSD::Date());
202        map.insert("URI",       LLSD::URI());
203        map.insert("Binary",    LLSD::Binary());
204        map.insert("Map",       LLSD().with("foo", LLSD()));
205        // Only an empty array can be constructed on the fly
206        LLSD array;
207        array.append(LLSD());
208        map.insert("Array",     array);
209
210        // These iterators are declared outside our various for loops to avoid
211        // fatal MSVC warning: "I used to be broken, but I'm all better now!"
212        LLSD::map_const_iterator mi, mend(map.endMap());
213
214        /*-------------------------- llsd_matches --------------------------*/
215
216        // empty prototype matches anything
217        for (mi = map.beginMap(); mi != mend; ++mi)
218        {
219            ensure_equals(std::string("empty matches ") + mi->first, llsd_matches(LLSD(), mi->second), "");
220        }
221
222        LLSD proto_array, data_array;
223        for (int i = 0; i < 3; ++i)
224        {
225            proto_array.append(LLSD());
226            data_array.append(LLSD());
227        }
228
229        // prototype array matches only array
230        for (mi = map.beginMap(); mi != mend; ++mi)
231        {
232            ensure(std::string("array doesn't match ") + mi->first,
233                   ! llsd_matches(proto_array, mi->second).empty());
234        }
235
236        // data array must be at least as long as prototype array
237        proto_array.append(LLSD());
238        ensure_equals("data array too short", llsd_matches(proto_array, data_array),
239                      "Array size 4 required instead of Array size 3");
240        data_array.append(LLSD());
241        ensure_equals("data array just right", llsd_matches(proto_array, data_array), "");
242        data_array.append(LLSD());
243        ensure_equals("data array longer", llsd_matches(proto_array, data_array), "");
244
245        // array element matching
246        data_array[0] = LLSD::String();
247        ensure_equals("undefined prototype array entry", llsd_matches(proto_array, data_array), "");
248        proto_array[0] = LLSD::Binary();
249        ensure_equals("scalar prototype array entry", llsd_matches(proto_array, data_array),
250                      "[0]: Binary required instead of String");
251        data_array[0] = LLSD::Binary();
252        ensure_equals("matching prototype array entry", llsd_matches(proto_array, data_array), "");
253
254        // build a coupla maps
255        LLSD proto_map, data_map;
256        data_map["got"] = LLSD();
257        data_map["found"] = LLSD();
258        for (LLSD::map_const_iterator dmi(data_map.beginMap()), dmend(data_map.endMap());
259             dmi != dmend; ++dmi)
260        {
261            proto_map[dmi->first] = dmi->second;
262        }
263        proto_map["foo"] = LLSD();
264        proto_map["bar"] = LLSD();
265
266        // prototype map matches only map
267        for (mi = map.beginMap(); mi != mend; ++mi)
268        {
269            ensure(std::string("map doesn't match ") + mi->first,
270                   ! llsd_matches(proto_map, mi->second).empty());
271        }
272
273        // data map must contain all keys in prototype map
274        std::string error(llsd_matches(proto_map, data_map));
275        ensure_contains("missing keys", error, "missing keys");
276        ensure_contains("missing foo", error, "foo");
277        ensure_contains("missing bar", error, "bar");
278        ensure_does_not_contain("found found", error, "found");
279        ensure_does_not_contain("got got", error, "got");
280        data_map["bar"] = LLSD();
281        error = llsd_matches(proto_map, data_map);
282        ensure_contains("missing foo", error, "foo");
283        ensure_does_not_contain("got bar", error, "bar");
284        data_map["foo"] = LLSD();
285        ensure_equals("data map just right", llsd_matches(proto_map, data_map), "");
286        data_map["extra"] = LLSD();
287        ensure_equals("data map with extra", llsd_matches(proto_map, data_map), "");
288
289        // map element matching
290        data_map["foo"] = LLSD::String();
291        ensure_equals("undefined prototype map entry", llsd_matches(proto_map, data_map), "");
292        proto_map["foo"] = LLSD::Binary();
293        ensure_equals("scalar prototype map entry", llsd_matches(proto_map, data_map),
294                      "['foo']: Binary required instead of String");
295        data_map["foo"] = LLSD::Binary();
296        ensure_equals("matching prototype map entry", llsd_matches(proto_map, data_map), "");
297
298        // String
299        {
300            static const char* matches[] = { "String", "NumString", "Boolean", "Integer",
301                                             "Real", "UUID", "Date", "URI" };
302            test_matches("String", map, boost::begin(matches), boost::end(matches));
303        }
304
305        // Boolean, Integer, Real
306        static const char* numerics[] = { "Boolean", "Integer", "Real" };
307        for (const char **ni = boost::begin(numerics), **nend = boost::end(numerics);
308             ni != nend; ++ni)
309        {
310            static const char* matches[] = { "Boolean", "Integer", "Real", "String", "NumString" };
311            test_matches(*ni, map, boost::begin(matches), boost::end(matches));
312        }
313
314        // UUID
315        {
316            static const char* matches[] = { "UUID", "String", "NumString" };
317            test_matches("UUID", map, boost::begin(matches), boost::end(matches));
318        }
319
320        // Date
321        {
322            static const char* matches[] = { "Date", "String", "NumString" };
323            test_matches("Date", map, boost::begin(matches), boost::end(matches));
324        }
325
326        // URI
327        {
328            static const char* matches[] = { "URI", "String", "NumString" };
329            test_matches("URI", map, boost::begin(matches), boost::end(matches));
330        }
331
332        // Binary
333        {
334            static const char* matches[] = { "Binary" };
335            test_matches("Binary", map, boost::begin(matches), boost::end(matches));
336        }
337
338        /*-------------------------- llsd_equals ---------------------------*/
339
340        // Cross-product of each LLSD type with every other
341        for (LLSD::map_const_iterator lmi(map.beginMap()), lmend(map.endMap());
342             lmi != lmend; ++lmi)
343        {
344            for (LLSD::map_const_iterator rmi(map.beginMap()), rmend(map.endMap());
345                 rmi != rmend; ++rmi)
346            {
347                // Name this test based on the map keys naming the types of
348                // interest, e.g "String::Integer".
349                // We expect the values (xmi->second) to be equal if and only
350                // if the type names (xmi->first) are equal.
351                ensure(STRINGIZE(lmi->first << "::" << rmi->first),
352                       bool(lmi->first == rmi->first) ==
353                       bool(llsd_equals(lmi->second, rmi->second)));
354            }
355        }
356
357        // Array cases
358        LLSD rarray;
359        rarray.append(1.0);
360        rarray.append(2);
361        rarray.append("3");
362        LLSD larray(rarray);
363        ensure("llsd_equals(equal arrays)", llsd_equals(larray, rarray));
364        rarray[2] = "4";
365        ensure("llsd_equals(different [2])", ! llsd_equals(larray, rarray));
366        rarray = larray;
367        rarray.append(LLSD::Date());
368        ensure("llsd_equals(longer right array)", ! llsd_equals(larray, rarray));
369        rarray = larray;
370        rarray.erase(2);
371        ensure("llsd_equals(shorter right array)", ! llsd_equals(larray, rarray));
372
373        // Map cases
374        LLSD rmap;
375        rmap["San Francisco"] = 65;
376        rmap["Phoenix"] = 92;
377        rmap["Boston"] = 77;
378        LLSD lmap(rmap);
379        ensure("llsd_equals(equal maps)", llsd_equals(lmap, rmap));
380        rmap["Boston"] = 80;
381        ensure("llsd_equals(different [\"Boston\"])", ! llsd_equals(lmap, rmap));
382        rmap = lmap;
383        rmap["Atlanta"] = 95;
384        ensure("llsd_equals(superset right map)", ! llsd_equals(lmap, rmap));
385        rmap = lmap;
386        lmap["Seattle"] = 72;
387        ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
388    }
389}