llhttpnode_tut.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:12k
- /**
- * @file lliohttpnode_tut.cpp
- * @date May 2006
- * @brief HTTP server unit tests
- *
- * $LicenseInfo:firstyear=2006&license=viewergpl$
- *
- * Copyright (c) 2006-2010, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "lltut.h"
- #include "llhttpnode.h"
- #include "llsdhttpserver.h"
- namespace tut
- {
- struct HTTPNodeTestData
- {
- LLHTTPNode mRoot;
- LLSD mContext;
-
- const LLSD& context() { return mContext; }
-
- std::string remainderPath()
- {
- std::ostringstream pathOutput;
- bool addSlash = false;
-
- LLSD& remainder = mContext["request"]["remainder"];
- for (LLSD::array_const_iterator i = remainder.beginArray();
- i != remainder.endArray();
- ++i)
- {
- if (addSlash) { pathOutput << '/'; }
- pathOutput << i->asString();
- addSlash = true;
- }
-
- return pathOutput.str();
- }
-
- void ensureRootTraversal(const std::string& path,
- const LLHTTPNode* expectedNode,
- const char* expectedRemainder)
- {
- mContext.clear();
-
- const LLHTTPNode* actualNode = mRoot.traverse(path, mContext);
-
- ensure_equals("traverse " + path + " node",
- actualNode, expectedNode);
- ensure_equals("traverse " + path + " remainder",
- remainderPath(), expectedRemainder);
- }
- class Response : public LLHTTPNode::Response
- {
- public:
- static LLPointer<Response> create() {return new Response();}
- LLSD mResult;
- void result(const LLSD& result) { mResult = result; }
- void status(S32 code, const std::string& message) { }
- void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
-
- private:
- Response() {;} // Must be accessed through LLPointer.
- };
- typedef LLPointer<Response> ResponsePtr;
- LLSD get(const std::string& path)
- {
- mContext.clear();
- const LLHTTPNode* node = mRoot.traverse(path, mContext);
- ensure(path + " found", node != NULL);
- ResponsePtr response = Response::create();
- node->get(LLHTTPNode::ResponsePtr(response), mContext);
- return response->mResult;
- }
-
- LLSD post(const std::string& path, const LLSD& input)
- {
- mContext.clear();
- const LLHTTPNode* node = mRoot.traverse(path, mContext);
- ensure(path + " found", node != NULL);
- ResponsePtr response = Response::create();
- node->post(LLHTTPNode::ResponsePtr(response), mContext, input);
- return response->mResult;
- }
-
- void ensureMemberString(const std::string& name,
- const LLSD& actualMap, const std::string& member,
- const std::string& expectedValue)
- {
- ensure_equals(name + " " + member,
- actualMap[member].asString(), expectedValue);
- }
-
-
- void ensureInArray(const LLSD& actualArray,
- const std::string& expectedValue)
- {
- LLSD::array_const_iterator i = actualArray.beginArray();
- LLSD::array_const_iterator end = actualArray.endArray();
-
- for (; i != end; ++i)
- {
- std::string path = i->asString();
- if (path == expectedValue)
- {
- return;
- }
- }
-
- fail("didn't find " + expectedValue);
- }
-
- };
-
- typedef test_group<HTTPNodeTestData> HTTPNodeTestGroup;
- typedef HTTPNodeTestGroup::object HTTPNodeTestObject;
- HTTPNodeTestGroup httpNodeTestGroup("http node");
- template<> template<>
- void HTTPNodeTestObject::test<1>()
- {
- // traversal of the lone node
-
- ensureRootTraversal("", &mRoot, "");
- ensureRootTraversal("/", &mRoot, "");
- ensureRootTraversal("foo", NULL, "foo");
- ensureRootTraversal("foo/bar", NULL, "foo/bar");
-
- ensure_equals("root of root", mRoot.rootNode(), &mRoot);
- }
-
- template<> template<>
- void HTTPNodeTestObject::test<2>()
- {
- // simple traversal of a single node
-
- LLHTTPNode* helloNode = new LLHTTPNode;
- mRoot.addNode("hello", helloNode);
- ensureRootTraversal("hello", helloNode, "");
- ensureRootTraversal("/hello", helloNode, "");
- ensureRootTraversal("hello/", helloNode, "");
- ensureRootTraversal("/hello/", helloNode, "");
- ensureRootTraversal("hello/there", NULL, "there");
-
- ensure_equals("root of hello", helloNode->rootNode(), &mRoot);
- }
- template<> template<>
- void HTTPNodeTestObject::test<3>()
- {
- // traversal of mutli-branched tree
-
- LLHTTPNode* greekNode = new LLHTTPNode;
- LLHTTPNode* alphaNode = new LLHTTPNode;
- LLHTTPNode* betaNode = new LLHTTPNode;
- LLHTTPNode* gammaNode = new LLHTTPNode;
-
- greekNode->addNode("alpha", alphaNode);
- greekNode->addNode("beta", betaNode);
- greekNode->addNode("gamma", gammaNode);
- mRoot.addNode("greek", greekNode);
-
- LLHTTPNode* hebrewNode = new LLHTTPNode;
- LLHTTPNode* alephNode = new LLHTTPNode;
-
- hebrewNode->addNode("aleph", alephNode);
- mRoot.addNode("hebrew", hebrewNode);
- ensureRootTraversal("greek/alpha", alphaNode, "");
- ensureRootTraversal("greek/beta", betaNode, "");
- ensureRootTraversal("greek/delta", NULL, "delta");
- ensureRootTraversal("greek/gamma", gammaNode, "");
- ensureRootTraversal("hebrew/aleph", alephNode, "");
- ensure_equals("root of greek", greekNode->rootNode(), &mRoot);
- ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
- ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
- ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
- ensure_equals("root of hebrew", hebrewNode->rootNode(), &mRoot);
- ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
- }
- template<> template<>
- void HTTPNodeTestObject::test<4>()
- {
- // automatic creation of parent nodes and not overriding existing nodes
-
- LLHTTPNode* alphaNode = new LLHTTPNode;
- LLHTTPNode* betaNode = new LLHTTPNode;
- LLHTTPNode* gammaNode = new LLHTTPNode;
- LLHTTPNode* gamma2Node = new LLHTTPNode;
-
- mRoot.addNode("greek/alpha", alphaNode);
- mRoot.addNode("greek/beta", betaNode);
-
- mRoot.addNode("greek/gamma", gammaNode);
- mRoot.addNode("greek/gamma", gamma2Node);
-
- LLHTTPNode* alephNode = new LLHTTPNode;
-
- mRoot.addNode("hebrew/aleph", alephNode);
- ensureRootTraversal("greek/alpha", alphaNode, "");
- ensureRootTraversal("greek/beta", betaNode, "");
- ensureRootTraversal("greek/delta", NULL, "delta");
- ensureRootTraversal("greek/gamma", gammaNode, "");
- ensureRootTraversal("hebrew/aleph", alephNode, "");
- ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
- ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
- ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
- ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
- }
-
- class IntegerNode : public LLHTTPNode
- {
- public:
- virtual void get(ResponsePtr response, const LLSD& context) const
- {
- int n = context["extra"]["value"];
-
- LLSD info;
- info["value"] = n;
- info["positive"] = n > 0;
- info["zero"] = n == 0;
- info["negative"] = n < 0;
-
- response->result(info);
- }
-
- virtual bool validate(const std::string& name, LLSD& context) const
- {
- int n;
- std::istringstream i_stream(name);
- i_stream >> n;
- if (i_stream.fail() || i_stream.get() != EOF)
- {
- return false;
- }
- context["extra"]["value"] = n;
- return true;
- }
- };
-
- class SquareNode : public LLHTTPNode
- {
- public:
- virtual void get(ResponsePtr response, const LLSD& context) const
- {
- int n = context["extra"]["value"];
- response->result(n*n);
- }
- };
-
- template<> template<>
- void HTTPNodeTestObject::test<5>()
- {
- // wildcard nodes
-
- LLHTTPNode* miscNode = new LLHTTPNode;
- LLHTTPNode* iNode = new IntegerNode;
- LLHTTPNode* sqNode = new SquareNode;
-
- mRoot.addNode("test/misc", miscNode);
- mRoot.addNode("test/<int>", iNode);
- mRoot.addNode("test/<int>/square", sqNode);
-
- ensureRootTraversal("test/42", iNode, "");
- ensure_equals("stored integer",
- context()["extra"]["value"].asInteger(), 42);
-
- ensureRootTraversal("test/bob", NULL, "bob");
- ensure("nothing stored",
- context()["extra"]["value"].isUndefined());
-
- ensureRootTraversal("test/3/square", sqNode, "");
- ResponsePtr response = Response::create();
- sqNode->get(LLHTTPNode::ResponsePtr(response), context());
- ensure_equals("square result", response->mResult.asInteger(), 9);
- }
-
- class AlphaNode : public LLHTTPNode
- {
- public:
- virtual bool handles(const LLSD& remainder, LLSD& context) const
- {
- LLSD::array_const_iterator i = remainder.beginArray();
- LLSD::array_const_iterator end = remainder.endArray();
-
- for (; i != end; ++i)
- {
- std::string s = i->asString();
- if (s.empty() || s[0] != 'a')
- {
- return false;
- }
- }
-
- return true;
- }
- };
-
- template<> template<>
- void HTTPNodeTestObject::test<6>()
- {
- // nodes that handle remainders
-
- LLHTTPNode* miscNode = new LLHTTPNode;
- LLHTTPNode* aNode = new AlphaNode;
- LLHTTPNode* zNode = new LLHTTPNode;
-
- mRoot.addNode("test/misc", miscNode);
- mRoot.addNode("test/alpha", aNode);
- mRoot.addNode("test/alpha/zebra", zNode);
-
- ensureRootTraversal("test/alpha", aNode, "");
- ensureRootTraversal("test/alpha/abe", aNode, "abe");
- ensureRootTraversal("test/alpha/abe/amy", aNode, "abe/amy");
- ensureRootTraversal("test/alpha/abe/bea", NULL, "abe/bea");
- ensureRootTraversal("test/alpha/bob", NULL, "bob");
- ensureRootTraversal("test/alpha/zebra", zNode, "");
- }
-
- template<> template<>
- void HTTPNodeTestObject::test<7>()
- {
- // test auto registration
-
- LLHTTPStandardServices::useServices();
- LLHTTPRegistrar::buildAllServices(mRoot);
-
- {
- LLSD result = get("web/hello");
- ensure_equals("hello result", result.asString(), "hello");
- }
- {
- LLSD stuff = 3.14159;
- LLSD result = post("web/echo", stuff);
- ensure_equals("echo result", result, stuff);
- }
- }
- template<> template<>
- void HTTPNodeTestObject::test<8>()
- {
- // test introspection
-
- LLHTTPRegistrar::buildAllServices(mRoot);
-
- mRoot.addNode("test/misc", new LLHTTPNode);
- mRoot.addNode("test/<int>", new IntegerNode);
- mRoot.addNode("test/<int>/square", new SquareNode);
- const LLSD result = get("web/server/api");
-
- ensure("result is array", result.isArray());
- ensure("result size", result.size() >= 2);
-
- ensureInArray(result, "web/echo");
- ensureInArray(result, "web/hello");
- ensureInArray(result, "test/misc");
- ensureInArray(result, "test/<int>");
- ensureInArray(result, "test/<int>/square");
- }
-
- template<> template<>
- void HTTPNodeTestObject::test<9>()
- {
- // test introspection details
- LLHTTPRegistrar::buildAllServices(mRoot);
- const LLSD helloDetails = get("web/server/api/web/hello");
-
- ensure_contains("hello description",
- helloDetails["description"].asString(), "hello");
- ensure_equals("method name", helloDetails["api"][0].asString(), std::string("GET"));
- ensureMemberString("hello", helloDetails, "output", ""hello"");
- ensure_contains("hello __file__",
- helloDetails["__file__"].asString(), "llsdhttpserver.cpp");
- ensure("hello line", helloDetails["__line__"].isInteger());
- const LLSD echoDetails = get("web/server/api/web/echo");
-
- ensure_contains("echo description",
- echoDetails["description"].asString(), "echo");
- ensure_equals("method name", echoDetails["api"][0].asString(), std::string("POST"));
- ensureMemberString("echo", echoDetails, "input", "<any>");
- ensureMemberString("echo", echoDetails, "output", "<the input>");
- ensure_contains("echo __file__",
- echoDetails["__file__"].asString(), "llsdhttpserver.cpp");
- ensure("echo", echoDetails["__line__"].isInteger());
- }
- }