aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/test/llhttpnode_tut.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/test/llhttpnode_tut.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/test/llhttpnode_tut.cpp')
-rw-r--r--linden/indra/test/llhttpnode_tut.cpp428
1 files changed, 428 insertions, 0 deletions
diff --git a/linden/indra/test/llhttpnode_tut.cpp b/linden/indra/test/llhttpnode_tut.cpp
new file mode 100644
index 0000000..006ba09
--- /dev/null
+++ b/linden/indra/test/llhttpnode_tut.cpp
@@ -0,0 +1,428 @@
1/**
2 * @file lliohttpserver_tut.cpp
3 * @date May 2006
4 * @brief HTTP server unit tests
5 *
6 * Copyright (c) 2006-2007, Linden Research, Inc.
7 *
8 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement
11 * ("Other License"), formally executed by you and Linden Lab. Terms of
12 * the GPL can be found in doc/GPL-license.txt in this distribution, or
13 * online at http://secondlife.com/developers/opensource/gplv2
14 *
15 * There are special exceptions to the terms and conditions of the GPL as
16 * it is applied to this Source Code. View the full text of the exception
17 * in the file doc/FLOSS-exception.txt in this software distribution, or
18 * online at http://secondlife.com/developers/opensource/flossexception
19 *
20 * By copying, modifying or distributing this software, you acknowledge
21 * that you have read and understood your obligations described above,
22 * and agree to abide by those obligations.
23 *
24 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
25 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
26 * COMPLETENESS OR PERFORMANCE.
27 */
28
29#include <tut/tut.h>
30#include "lltut.h"
31
32#include "llhttpnode.h"
33#include "llsdhttpserver.h"
34
35namespace tut
36{
37 struct HTTPNodeTestData
38 {
39 LLHTTPNode mRoot;
40 LLSD mContext;
41
42 const LLSD& context() { return mContext; }
43
44 std::string remainderPath()
45 {
46 std::ostringstream pathOutput;
47 bool addSlash = false;
48
49 LLSD& remainder = mContext["request"]["remainder"];
50 for (LLSD::array_const_iterator i = remainder.beginArray();
51 i != remainder.endArray();
52 ++i)
53 {
54 if (addSlash) { pathOutput << '/'; }
55 pathOutput << i->asString();
56 addSlash = true;
57 }
58
59 return pathOutput.str();
60 }
61
62 void ensureRootTraversal(const std::string& path,
63 const LLHTTPNode* expectedNode,
64 const char* expectedRemainder)
65 {
66 mContext.clear();
67
68 const LLHTTPNode* actualNode = mRoot.traverse(path, mContext);
69
70 ensure_equals("traverse " + path + " node",
71 actualNode, expectedNode);
72 ensure_equals("traverse " + path + " remainder",
73 remainderPath(), expectedRemainder);
74 }
75
76 class Response : public LLHTTPNode::Response
77 {
78 public:
79 static LLPointer<Response> create() {return new Response();}
80
81 LLSD mResult;
82
83 void result(const LLSD& result) { mResult = result; }
84 void status(S32 code, const std::string& message) { }
85
86 private:
87 Response() {;} // Must be accessed through LLPointer.
88 };
89
90 typedef LLPointer<Response> ResponsePtr;
91
92 LLSD get(const std::string& path)
93 {
94 mContext.clear();
95 const LLHTTPNode* node = mRoot.traverse(path, mContext);
96 ensure(path + " found", node != NULL);
97
98 ResponsePtr response = Response::create();
99 node->get(LLHTTPNode::ResponsePtr(response), mContext);
100 return response->mResult;
101 }
102
103 LLSD post(const std::string& path, const LLSD& input)
104 {
105 mContext.clear();
106 const LLHTTPNode* node = mRoot.traverse(path, mContext);
107 ensure(path + " found", node != NULL);
108
109 ResponsePtr response = Response::create();
110 node->post(LLHTTPNode::ResponsePtr(response), mContext, input);
111 return response->mResult;
112 }
113
114 void ensureMemberString(const std::string& name,
115 const LLSD& actualMap, const std::string& member,
116 const std::string& expectedValue)
117 {
118 ensure_equals(name + " " + member,
119 actualMap[member].asString(), expectedValue);
120 }
121
122
123 void ensureInArray(const LLSD& actualArray,
124 const std::string& expectedValue)
125 {
126 LLSD::array_const_iterator i = actualArray.beginArray();
127 LLSD::array_const_iterator end = actualArray.endArray();
128
129 for (; i != end; ++i)
130 {
131 std::string path = i->asString();
132
133 if (path == expectedValue)
134 {
135 return;
136 }
137 }
138
139 fail("didn't find " + expectedValue);
140 }
141
142 };
143
144 typedef test_group<HTTPNodeTestData> HTTPNodeTestGroup;
145 typedef HTTPNodeTestGroup::object HTTPNodeTestObject;
146 HTTPNodeTestGroup httpNodeTestGroup("http node");
147
148 template<> template<>
149 void HTTPNodeTestObject::test<1>()
150 {
151 // traversal of the lone node
152
153 ensureRootTraversal("", &mRoot, "");
154 ensureRootTraversal("/", &mRoot, "");
155 ensureRootTraversal("foo", NULL, "foo");
156 ensureRootTraversal("foo/bar", NULL, "foo/bar");
157
158 ensure_equals("root of root", mRoot.rootNode(), &mRoot);
159 }
160
161 template<> template<>
162 void HTTPNodeTestObject::test<2>()
163 {
164 // simple traversal of a single node
165
166 LLHTTPNode* helloNode = new LLHTTPNode;
167 mRoot.addNode("hello", helloNode);
168
169 ensureRootTraversal("hello", helloNode, "");
170 ensureRootTraversal("/hello", helloNode, "");
171 ensureRootTraversal("hello/", helloNode, "");
172 ensureRootTraversal("/hello/", helloNode, "");
173
174 ensureRootTraversal("hello/there", NULL, "there");
175
176 ensure_equals("root of hello", helloNode->rootNode(), &mRoot);
177 }
178
179 template<> template<>
180 void HTTPNodeTestObject::test<3>()
181 {
182 // traversal of mutli-branched tree
183
184 LLHTTPNode* greekNode = new LLHTTPNode;
185 LLHTTPNode* alphaNode = new LLHTTPNode;
186 LLHTTPNode* betaNode = new LLHTTPNode;
187 LLHTTPNode* gammaNode = new LLHTTPNode;
188
189 greekNode->addNode("alpha", alphaNode);
190 greekNode->addNode("beta", betaNode);
191 greekNode->addNode("gamma", gammaNode);
192 mRoot.addNode("greek", greekNode);
193
194 LLHTTPNode* hebrewNode = new LLHTTPNode;
195 LLHTTPNode* alephNode = new LLHTTPNode;
196
197 hebrewNode->addNode("aleph", alephNode);
198 mRoot.addNode("hebrew", hebrewNode);
199
200 ensureRootTraversal("greek/alpha", alphaNode, "");
201 ensureRootTraversal("greek/beta", betaNode, "");
202 ensureRootTraversal("greek/delta", NULL, "delta");
203 ensureRootTraversal("greek/gamma", gammaNode, "");
204 ensureRootTraversal("hebrew/aleph", alephNode, "");
205
206 ensure_equals("root of greek", greekNode->rootNode(), &mRoot);
207 ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
208 ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
209 ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
210 ensure_equals("root of hebrew", hebrewNode->rootNode(), &mRoot);
211 ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
212 }
213
214 template<> template<>
215 void HTTPNodeTestObject::test<4>()
216 {
217 // automatic creation of parent nodes and not overriding existing nodes
218
219 LLHTTPNode* alphaNode = new LLHTTPNode;
220 LLHTTPNode* betaNode = new LLHTTPNode;
221 LLHTTPNode* gammaNode = new LLHTTPNode;
222 LLHTTPNode* gamma2Node = new LLHTTPNode;
223
224 mRoot.addNode("greek/alpha", alphaNode);
225 mRoot.addNode("greek/beta", betaNode);
226
227 mRoot.addNode("greek/gamma", gammaNode);
228 mRoot.addNode("greek/gamma", gamma2Node);
229
230 LLHTTPNode* alephNode = new LLHTTPNode;
231
232 mRoot.addNode("hebrew/aleph", alephNode);
233
234 ensureRootTraversal("greek/alpha", alphaNode, "");
235 ensureRootTraversal("greek/beta", betaNode, "");
236 ensureRootTraversal("greek/delta", NULL, "delta");
237 ensureRootTraversal("greek/gamma", gammaNode, "");
238 ensureRootTraversal("hebrew/aleph", alephNode, "");
239
240 ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
241 ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
242 ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
243 ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
244 }
245
246 class IntegerNode : public LLHTTPNode
247 {
248 public:
249 virtual void get(ResponsePtr response, const LLSD& context) const
250 {
251 int n = context["extra"]["value"];
252
253 LLSD info;
254 info["value"] = n;
255 info["positive"] = n > 0;
256 info["zero"] = n == 0;
257 info["negative"] = n < 0;
258
259 response->result(info);
260 }
261
262 virtual bool validate(const std::string& name, LLSD& context) const
263 {
264 int n;
265 std::istringstream i_stream(name);
266 i_stream >> n;
267
268 if (i_stream.fail() || i_stream.get() != EOF)
269 {
270 return false;
271 }
272
273 context["extra"]["value"] = n;
274 return true;
275 }
276 };
277
278 class SquareNode : public LLHTTPNode
279 {
280 public:
281 virtual void get(ResponsePtr response, const LLSD& context) const
282 {
283 int n = context["extra"]["value"];
284 response->result(n*n);
285 }
286 };
287
288 template<> template<>
289 void HTTPNodeTestObject::test<5>()
290 {
291 // wildcard nodes
292
293 LLHTTPNode* miscNode = new LLHTTPNode;
294 LLHTTPNode* iNode = new IntegerNode;
295 LLHTTPNode* sqNode = new SquareNode;
296
297 mRoot.addNode("test/misc", miscNode);
298 mRoot.addNode("test/<int>", iNode);
299 mRoot.addNode("test/<int>/square", sqNode);
300
301 ensureRootTraversal("test/42", iNode, "");
302 ensure_equals("stored integer",
303 context()["extra"]["value"].asInteger(), 42);
304
305 ensureRootTraversal("test/bob", NULL, "bob");
306 ensure("nothing stored",
307 context()["extra"]["value"].isUndefined());
308
309 ensureRootTraversal("test/3/square", sqNode, "");
310 ResponsePtr response = Response::create();
311 sqNode->get(LLHTTPNode::ResponsePtr(response), context());
312 ensure_equals("square result", response->mResult.asInteger(), 9);
313 }
314
315 class AlphaNode : public LLHTTPNode
316 {
317 public:
318 virtual bool handles(const LLSD& remainder, LLSD& context) const
319 {
320 LLSD::array_const_iterator i = remainder.beginArray();
321 LLSD::array_const_iterator end = remainder.endArray();
322
323 for (; i != end; ++i)
324 {
325 std::string s = i->asString();
326 if (s.empty() || s[0] != 'a')
327 {
328 return false;
329 }
330 }
331
332 return true;
333 }
334 };
335
336 template<> template<>
337 void HTTPNodeTestObject::test<6>()
338 {
339 // nodes that handle remainders
340
341 LLHTTPNode* miscNode = new LLHTTPNode;
342 LLHTTPNode* aNode = new AlphaNode;
343 LLHTTPNode* zNode = new LLHTTPNode;
344
345 mRoot.addNode("test/misc", miscNode);
346 mRoot.addNode("test/alpha", aNode);
347 mRoot.addNode("test/alpha/zebra", zNode);
348
349 ensureRootTraversal("test/alpha", aNode, "");
350 ensureRootTraversal("test/alpha/abe", aNode, "abe");
351 ensureRootTraversal("test/alpha/abe/amy", aNode, "abe/amy");
352 ensureRootTraversal("test/alpha/abe/bea", NULL, "abe/bea");
353 ensureRootTraversal("test/alpha/bob", NULL, "bob");
354 ensureRootTraversal("test/alpha/zebra", zNode, "");
355 }
356
357 template<> template<>
358 void HTTPNodeTestObject::test<7>()
359 {
360 // test auto registration
361
362 LLHTTPStandardServices::useServices();
363 LLHTTPRegistrar::buildAllServices(mRoot);
364
365 {
366 LLSD result = get("web/hello");
367 ensure_equals("hello result", result.asString(), "hello");
368 }
369 {
370 LLSD stuff = 3.14159;
371 LLSD result = post("web/echo", stuff);
372 ensure_equals("echo result", result, stuff);
373 }
374 }
375
376 template<> template<>
377 void HTTPNodeTestObject::test<8>()
378 {
379 // test introspection
380
381 LLHTTPRegistrar::buildAllServices(mRoot);
382
383 mRoot.addNode("test/misc", new LLHTTPNode);
384 mRoot.addNode("test/<int>", new IntegerNode);
385 mRoot.addNode("test/<int>/square", new SquareNode);
386
387 const LLSD result = get("web/server/api");
388
389 ensure("result is array", result.isArray());
390 ensure("result size", result.size() >= 2);
391
392 ensureInArray(result, "web/echo");
393 ensureInArray(result, "web/hello");
394 ensureInArray(result, "test/misc");
395 ensureInArray(result, "test/<int>");
396 ensureInArray(result, "test/<int>/square");
397 }
398
399 template<> template<>
400 void HTTPNodeTestObject::test<9>()
401 {
402 // test introspection details
403
404 LLHTTPRegistrar::buildAllServices(mRoot);
405
406 const LLSD helloDetails = get("web/server/api/web/hello");
407
408 ensure_contains("hello description",
409 helloDetails["description"].asString(), "hello");
410 ensure_equals("method name", helloDetails["api"][0].asString(), std::string("GET"));
411 ensureMemberString("hello", helloDetails, "output", "\"hello\"");
412 ensure_contains("hello __file__",
413 helloDetails["__file__"].asString(), "llsdhttpserver.cpp");
414 ensure("hello line", helloDetails["__line__"].isInteger());
415
416
417 const LLSD echoDetails = get("web/server/api/web/echo");
418
419 ensure_contains("echo description",
420 echoDetails["description"].asString(), "echo");
421 ensure_equals("method name", echoDetails["api"][0].asString(), std::string("POST"));
422 ensureMemberString("echo", echoDetails, "input", "<any>");
423 ensureMemberString("echo", echoDetails, "output", "<the input>");
424 ensure_contains("echo __file__",
425 echoDetails["__file__"].asString(), "llsdhttpserver.cpp");
426 ensure("echo", echoDetails["__line__"].isInteger());
427 }
428}