doc/commands: introduce command initialization from HTTP requests
authorAlexandre Terrasa <alexandre@moz-code.org>
Tue, 24 Oct 2017 20:35:36 +0000 (16:35 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Thu, 23 Nov 2017 16:08:40 +0000 (11:08 -0500)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/doc/commands/commands_http.nit [new file with mode: 0644]
src/doc/commands/tests/test_commands_http.nit [new file with mode: 0644]

diff --git a/src/doc/commands/commands_http.nit b/src/doc/commands/commands_http.nit
new file mode 100644 (file)
index 0000000..83f2ef1
--- /dev/null
@@ -0,0 +1,165 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Initialize commands from HTTP requests
+#
+# FIXME: this module is pretty tied up to the nitwed routes.
+# To be more generic, param names should be extracted as variables.
+module commands_http
+
+import commands
+import commands::commands_catalog
+import nitcorn::vararg_routes
+
+redef class DocCommand
+       # Init the command from an HTTPRequest
+       fun http_init(req: HttpRequest): CmdMessage do return init_command
+end
+
+redef class CmdEntity
+
+
+       redef fun http_init(req) do
+               var name = req.param("id")
+               if name != null then name = name.from_percent_encoding
+               self.mentity_name = name
+
+               return super
+       end
+end
+
+redef class CmdList
+       redef fun http_init(req) do
+               limit = req.int_arg("l")
+               page = req.int_arg("p")
+               return super
+       end
+end
+
+# Error Handling
+
+# Message handling
+
+redef class CmdMessage
+       # HTTP code to return for this message
+       var http_status_code = 200
+end
+
+redef class CmdError
+       redef var http_status_code = 400
+end
+
+redef class CmdWarning
+       redef var http_status_code = 404
+end
+
+redef class ErrorMEntityNoName
+       redef var http_status_code = 400
+end
+
+redef class ErrorMEntityNotFound
+       redef var http_status_code = 404
+end
+
+redef class ErrorMEntityConflict
+       redef var http_status_code = 300
+end
+
+# CmdModel
+
+redef class CmdComment
+       redef fun http_init(req) do
+               full_doc = req.bool_arg("full_doc") or else true
+               fallback = req.bool_arg("fallback") or else true
+               format = req.string_arg("format") or else "raw"
+               return super
+       end
+end
+
+redef class CmdAncestors
+       redef fun http_init(req) do
+               parents = req.bool_arg("parents") or else true
+               return super
+       end
+end
+
+redef class CmdDescendants
+       redef fun http_init(req) do
+               children = req.bool_arg("children") or else true
+               return super
+       end
+end
+
+redef class CmdEntityList
+       # FIXME avoid linearization conflict
+       redef fun http_init(req) do return super
+end
+
+redef class CmdSearch
+       redef fun http_init(req) do
+               query = req.string_arg("q")
+               return super
+       end
+end
+
+redef class CmdModelEntities
+       redef fun http_init(req) do
+               kind = req.string_arg("kind") or else "all"
+               return super
+       end
+end
+
+redef class CmdCode
+       redef fun http_init(req) do
+               format = req.string_arg("format") or else "raw"
+               return super
+       end
+end
+
+# CmdGraph
+
+redef class CmdGraph
+       redef fun http_init(req) do
+               format = req.string_arg("format") or else "dot"
+               return super
+       end
+end
+
+redef class CmdInheritanceGraph
+       redef fun http_init(req) do
+               pdepth = req.int_arg("pdepth")
+               cdepth = req.int_arg("cdepth")
+               return super
+       end
+end
+
+# CmdCatalog
+
+redef class CmdCatalogTag
+       redef fun http_init(req) do
+               var tag = req.param("tid")
+               if tag != null then tag = tag.from_percent_encoding
+               self.tag = tag
+               return super
+       end
+end
+
+redef class CmdCatalogPerson
+       redef fun http_init(req) do
+               var name = req.param("pid")
+               if name != null then name = name.from_percent_encoding
+               self.person_name = name
+               return super
+       end
+end
diff --git a/src/doc/commands/tests/test_commands_http.nit b/src/doc/commands/tests/test_commands_http.nit
new file mode 100644 (file)
index 0000000..4b0f6b7
--- /dev/null
@@ -0,0 +1,289 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_commands_http is test
+
+import doc::commands::test_commands_catalog
+import doc::commands::commands_http
+
+class TestCommandsHttp
+       super TestCommandsCatalog
+       test
+
+       # Http parser to create Http requests
+       var http_parser = new HttpRequestParser
+
+       # Create a new and initialized http request from the `url` string
+       fun new_request(url: String, route_pattern: nullable String): HttpRequest do
+               if route_pattern == null then route_pattern = "/:id"
+               var route = new Route(route_pattern, new TestDummyAction)
+               var req = http_parser.parse_http_request("GET {url} HTTP/1.0")
+               assert req != null
+               req.uri_params = route.parse_params(req.uri)
+               return req
+       end
+
+       # CmdEntity
+
+       fun test_cmd_http_entity is test do
+               var req = new_request("/test_prog::Character")
+               var cmd = new CmdEntity(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.mentity.as(not null).full_name == "test_prog::Character"
+       end
+
+       fun test_cmd_http_entity_not_found is test do
+               var req = new_request("/Characterzzz")
+               var cmd = new CmdEntity(test_view)
+               var res = cmd.http_init(req)
+               assert res isa ErrorMEntityNotFound
+               assert res.suggestions.first.full_name == "test_prog::Character"
+       end
+
+       fun test_cmd_http_entity_conflict is test do
+               var req = new_request("/+")
+               var cmd = new CmdEntity(test_view)
+               var res = cmd.http_init(req)
+               assert res isa ErrorMEntityConflict
+               assert res.conflicts.length == 2
+       end
+
+       # CmdComment
+
+       fun test_cmd_http_comment is test do
+               var req = new_request("/test_prog::Character")
+               var cmd = new CmdComment(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.mdoc != null
+       end
+
+       fun test_cmd_http_comment_no_mdoc is test do
+               var req = new_request("/test_prog::Character?fallback=false")
+               var cmd = new CmdComment(test_view)
+               var res = cmd.http_init(req)
+               assert res isa WarningNoMDoc
+       end
+
+       # CmdInheritance
+
+       fun test_cmd_http_parents is test do
+               var req = new_request("/test_prog::Warrior")
+               var cmd = new CmdParents(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 1
+       end
+
+       fun test_cmd_http_ancestors is test do
+               var req = new_request("/test_prog::Warrior")
+               var cmd = new CmdAncestors(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 2
+       end
+
+       fun test_cmd_http_ancestorsi_without_parents is test do
+               var req = new_request("/test_prog::Warrior?parents=false")
+               var cmd = new CmdAncestors(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 1
+       end
+
+       fun test_cmd_http_children is test do
+               var req = new_request("/test_prog::Career")
+               var cmd = new CmdChildren(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 3
+       end
+
+       fun test_cmd_http_descendants is test do
+               var req = new_request("/test_prog::Career?children=false")
+               var cmd = new CmdDescendants(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 0
+       end
+
+       # CmdSearch
+
+       fun test_cmd_http_search is test do
+               var req = new_request("/?q=Carer&l=1")
+               var cmd = new CmdSearch(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).first.full_name == "test_prog::Career"
+               assert cmd.results.as(not null).length == 1
+       end
+
+       fun test_cmd_http_search_no_query is test do
+               var req = new_request("/")
+               var cmd = new CmdSearch(test_view)
+               var res = cmd.http_init(req)
+               assert res isa ErrorNoQuery
+       end
+
+       # CmdFeatures
+
+       fun test_cmd_http_features is test do
+               var req = new_request("/test_prog::Character?l=10")
+               var cmd = new CmdFeatures(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 10
+       end
+
+       fun test_cmd_http_features_no_features is test do
+               var req = new_request("/test_prog$Career$strength_bonus?l=10")
+               var cmd = new CmdFeatures(test_view)
+               var res = cmd.http_init(req)
+               assert res isa WarningNoFeatures
+       end
+
+       # CmdLinearization
+
+       fun test_cmd_http_lin is test do
+               var req = new_request("/init?l=10")
+               var cmd = new CmdLinearization(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 10
+       end
+
+       fun test_cmd_http_lin_no_lin is test do
+               var req = new_request("/test_prog?l=10")
+               var cmd = new CmdLinearization(test_view)
+               var res = cmd.http_init(req)
+               assert res isa WarningNoLinearization
+       end
+
+       # CmdCode
+
+       fun test_cmd_http_code is test do
+               var req = new_request("/test_prog::Career")
+               var cmd = new CmdCode(test_view, test_builder)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.node isa AStdClassdef
+               assert cmd.format == "raw"
+       end
+
+       fun test_cmd_http_code_format is test do
+               var req = new_request("/test_prog::Career?format=html")
+               var cmd = new CmdCode(test_view, test_builder)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.node isa AStdClassdef
+               assert cmd.format == "html"
+       end
+
+       fun test_cmd_http_code_no_code is test do
+               var req = new_request("/test_prog")
+               var cmd = new CmdCode(test_view, test_builder)
+               var res = cmd.http_init(req)
+               assert res isa WarningNoCode
+       end
+
+       # CmdModel
+
+       fun test_cmd_http_results is test do
+               var req = new_request("/?kind=modules&l=2")
+               var cmd = new CmdModelEntities(test_view, kind = "modules")
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 2
+       end
+
+       fun test_cmd_http_results_random is test do
+               var req = new_request("/?kind=packages&l=1")
+               var cmd = new CmdRandomEntities(test_view, kind = "packages")
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 1
+       end
+
+       # CmdGraph
+
+       fun test_cmd_http_uml is test do
+               var req = new_request("/test_prog::Character?format=svg")
+               var cmd = new CmdUML(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.uml != null
+               assert cmd.format == "svg"
+       end
+
+       fun test_cmd_http_uml_not_found is test do
+               var req = new_request("/strength_bonus")
+               var cmd = new CmdUML(test_view)
+               var res = cmd.http_init(req)
+               assert res isa WarningNoUML
+               assert cmd.format == "dot"
+               assert cmd.uml == null
+       end
+
+       fun test_cmd_http_inh_graph is test do
+               var req = new_request("/test_prog::Character?pdepth=1&cdepth=1")
+               var cmd = new CmdInheritanceGraph(test_view)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.graph != null
+               assert cmd.pdepth == 1
+               assert cmd.cdepth == 1
+       end
+
+       # CmdCatalog
+
+       fun test_cmd_http_catalog_search is test do
+               var req = new_request("/?q=test&l=1")
+               var cmd = new CmdCatalogSearch(test_view, test_catalog)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).first.full_name == "test_prog"
+               assert cmd.results.as(not null).first isa MPackage
+               assert cmd.results.as(not null).length == 1
+       end
+
+       fun test_cmd_http_catalog_tag is test do
+               var req = new_request("/test", "/:tid")
+               var cmd = new CmdCatalogTag(test_view, test_catalog)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.tag == "test"
+               assert cmd.results.as(not null).length == 1
+       end
+
+       fun test_cmd_http_catalog_person is test do
+               var req = new_request("/Alexandre%20Terrasa", "/:pid")
+               var cmd = new CmdCatalogPerson(test_view, test_catalog)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.person.as(not null).name == "Alexandre Terrasa"
+       end
+end
+
+# Dummy action that does nothing
+#
+# Used to build the test route / http request.
+private class TestDummyAction
+       super Action
+end
+
+redef class CmdUML
+       # FIXME linerarization
+       redef fun http_init(req) do return super
+end