Imported packages where always shown. Not a good behavior on most command-line cases.
Pull-Request: #2168
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
c_src/** -diff
tests/sav/**/*.res -whitespace
-lib/popcorn/tests/res/*.res -whitespace
+*.res -whitespace
*.patch -whitespace
# limitations under the License.
# Test tools for NitRPG.
-module test_helper is test_suite
+module test_helper
import test_suite
import game
return res.to_s
end
- # Escape " \ ' and non printable characters using the rules of literal C strings and characters
+ # Escape `"` `\` `'`, trigraphs and non printable characters using the rules of literal C strings and characters
#
- # assert "abAB12<>&".escape_to_c == "abAB12<>&"
+ # assert "abAB12<>&".escape_to_c == "abAB12<>&"
# assert "\n\"'\\".escape_to_c == "\\n\\\"\\'\\\\"
+ # assert "allo???!".escape_to_c == "allo??\\?!"
+ # assert "??=??/??'??(??)".escape_to_c == "?\\?=?\\?/??\\'?\\?(?\\?)"
+ # assert "??!??<??>??-".escape_to_c == "?\\?!?\\?<?\\?>?\\?-"
#
# Most non-printable characters (bellow ASCII 32) are escaped to an octal form `\nnn`.
# Three digits are always used to avoid following digits to be interpreted as an element
b.append("\\\'")
else if c == '\\' then
b.append("\\\\")
+ else if c == '?' then
+ # Escape if it is the last question mark of a ANSI C trigraph.
+ var j = i + 1
+ if j < length then
+ var next = chars[j]
+ # We ignore `??'` because it will be escaped as `??\'`.
+ if
+ next == '!' or
+ next == '(' or
+ next == ')' or
+ next == '-' or
+ next == '/' or
+ next == '<' or
+ next == '=' or
+ next == '>'
+ then b.add('\\')
+ end
+ b.add('?')
else if c.code_point < 32 then
b.add('\\')
var oct = c.code_point.to_base(8)
# The result might no be legal in C but be used in other languages
#
# assert "ab|\{\}".escape_more_to_c("|\{\}") == "ab\\|\\\{\\\}"
+ # assert "allo???!".escape_more_to_c("") == "allo??\\?!"
fun escape_more_to_c(chars: String): String
do
var b = new Buffer
req_esc += 1
else if c == 0x5Cu8 then
req_esc += 1
+ else if c == 0x3Fu8 then
+ var j = pos + 1
+ if j < length then
+ var next = its[j]
+ # We ignore `??'` because it will be escaped as `??\'`.
+ if
+ next == 0x21u8 or
+ next == 0x28u8 or
+ next == 0x29u8 or
+ next == 0x2Du8 or
+ next == 0x2Fu8 or
+ next == 0x3Cu8 or
+ next == 0x3Du8 or
+ next == 0x3Eu8
+ then req_esc += 1
+ end
else if c < 32u8 then
req_esc += 3
end
nns[opos] = 0x5Cu8
nns[opos + 1] = 0x5Cu8
opos += 2
+ else if c == 0x3Fu8 then
+ var j = pos + 1
+ if j < length then
+ var next = its[j]
+ # We ignore `??'` because it will be escaped as `??\'`.
+ if
+ next == 0x21u8 or
+ next == 0x28u8 or
+ next == 0x29u8 or
+ next == 0x2Du8 or
+ next == 0x2Fu8 or
+ next == 0x3Cu8 or
+ next == 0x3Du8 or
+ next == 0x3Eu8
+ then
+ nns[opos] = 0x5Cu8
+ opos += 1
+ end
+ end
+ nns[opos] = 0x3Fu8
+ opos += 1
else if c < 32u8 then
nns[opos] = 0x5Cu8
nns[opos + 1] = 0x30u8
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT. This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. You can modify it is you want, provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You are allowed to redistribute it and sell it, alone or is a part of
+# another product.
+
+module test_abstract_text is test_suite
+
+import test_suite
+import text
+intrude import ropes
+
+class TestText
+ super TestSuite
+
+ private var factories: Collection[TextFactory] = [
+ new ConcatFactory,
+ new RopeBufferFactory,
+ new FlatBufferFactory
+ : TextFactory]
+
+ fun test_escape_to_c do
+ for f in factories do
+ assert f.create("abAB12<>&").escape_to_c == "abAB12<>&"
+ assert f.create("\n\"'\\").escape_to_c == "\\n\\\"\\'\\\\"
+ assert f.create("allo???!").escape_to_c == "allo??\\?!"
+ assert f.create("??=??/??'??(??)").escape_to_c == "?\\?=?\\?/??\\'?\\?(?\\?)"
+ assert f.create("??!??<??>??-").escape_to_c == "?\\?!?\\?<?\\?>?\\?-"
+ end
+ end
+end
+
+# A factory that creates instances of a particular implementation of `Text`
+interface TextFactory
+
+ # Create a `Text` instance from the specified string
+ fun create(s: String): Text is abstract
+end
+
+
+class ConcatFactory
+ super TextFactory
+
+ redef fun create(s) do return new Concat("", s)
+end
+
+class RopeBufferFactory
+ super TextFactory
+
+ redef fun create(s) do return new RopeBuffer.from(s)
+end
+
+class FlatBufferFactory
+ super TextFactory
+
+ redef fun create(s) do return new FlatBuffer.from(s)
+end
import nitcorn
+# Nitcorn Action used to answer requests.
class HTCPCPAction
super Action
+
+ # Brewing status.
var brewing = false
- var is_teapot = false
+
+ # Teapot status.
+ var is_teapot = false
redef fun answer(http_request, turi) do
var message: String
var method = http_request.method
- var headers = http_request.header
var response: HttpResponse
if is_teapot == true then
end
end
-
+# Nitcorn server.
class HTCPCServer
+
+ # Port to listen to.
var port: Int
+ # Start listening.
fun run do
var vh = new VirtualHost("localhost:{port}")
vh.routes.add new Route("/", new HTCPCPAction)
# A request received over HTTP, is build by `HttpRequestParser`
class HttpRequest
- private init do end
+ private init is old_style_init do end
# HTTP protocol version
var http_version: String
# Words of the first line
private var first_line = new Array[String]
+ # Parse the `first_line`, `header_fields` and `body` of `full_request`.
fun parse_http_request(full_request: String): nullable HttpRequest
do
clear_data
# All know code and their message
var codes = new HashMap[Int, String]
- protected init do insert_status_codes
+ # Init the status `codes` list.
+ protected init is old_style_init do insert_status_codes
# Get the message associated to the status `code`, return `null` in unknown
fun [](code: Int): nullable String
# Map of known MIME types
class MediaTypes
+
+ # MIME types by extensions.
protected var types = new HashMap[String, String]
# Get the type/subtype associated to a file extension `ext`
end
end
+# MIME types list.
fun media_types: MediaTypes do return once new MediaTypes
NITUNIT=../../bin/nitunit
check:
- $(NITUNIT) README.md
- $(NITUNIT) pop_routes.nit
- $(NITUNIT) pop_handlers.nit
- $(NITUNIT) popcorn.nit
- cd tests; make check
+ $(NITUNIT) .
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_angular is test_suite
+
+import pop_tests
import example_angular
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleAngular
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/counter"
system "curl -s {host}:{port}/counter -X POST"
system "curl -s {host}:{port}/counter"
system "curl -s {host}:{port}/not_found" # handled by angular controller
- return null
end
-end
-
-var app = new App
-app.use("/counter", new CounterAPI)
-app.use("/*", new StaticHandler("../examples/angular/www/", "index.html"))
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/counter", new CounterAPI)
+ app.use("/*", new StaticHandler("../examples/angular/www/", "index.html"))
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_post_handler is test_suite
+
+import pop_tests
import example_post_handler
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleQueryString
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/ -X POST"
system "curl -s {host}:{port}/ --data 'user'"
system "curl -s {host}:{port}/ --data 'user=Morriar'"
system "curl -s {host}:{port}/ --data 'user=\&order=desc'"
system "curl -s {host}:{port}/ --data 'user=Morriar\&order=desc'"
-
system "curl -s {host}:{port}/"
- return null
end
-end
-
-var app = new App
-app.use("/", new PostHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_glob_route do
+ var app = new App
+ app.use("/", new PostHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_query_string is test_suite
+
+import pop_tests
import example_query_string
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleQueryString
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/?user=Morriar"
system "curl -s {host}:{port}/?reload"
system "curl -s {host}:{port}/?foo\\&bar=baz"
system "curl -s {host}:{port}/?items=10\\&order=asc"
- return null
end
-end
-
-var app = new App
-app.use("/", new QueryStringHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_glob_route do
+ var app = new App
+ app.use("/", new QueryStringHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_hello is test_suite
+
+import pop_tests
import example_hello
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleHello
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}"
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}///////////"
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/not_found/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/", new HelloHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_hello do
+ var app = new App
+ app.use("/", new HelloHandler)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_advanced_logger is test_suite
+
+import pop_tests
import example_advanced_logger
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleAdvancedLogger
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use_before("/*", new RequestTimeHandler)
-app.use("/", new HelloHandler)
-app.use_after("/*", new LogHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use_before("/*", new RequestTimeHandler)
+ app.use("/", new HelloHandler)
+ app.use_after("/*", new LogHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_html_error_handler is test_suite
+
+import pop_tests
import example_html_error_handler
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleHtmlErrorHandler
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use("/*", new HtmlErrorHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/*", new HtmlErrorHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_simple_error_handler is test_suite
+
+import pop_tests
import example_simple_error_handler
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleSimpleErrorHandler
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use("/", new HelloHandler)
-app.use("/*", new SimpleErrorHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new HelloHandler)
+ app.use("/*", new SimpleErrorHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_simple_logger is test_suite
+
+import pop_tests
import example_simple_logger
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleSimpleLogger
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use_before("/*", new LogHandler)
-app.use("/", new HelloHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use_before("/*", new LogHandler)
+ app.use("/", new HelloHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_glob_route is test_suite
+
+import pop_tests
import example_glob_route
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleGlobRoute
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/user/Morriar/item/10"
system "curl -s {host}:{port}/user/Morriar/item/10/"
system "curl -s {host}:{port}/user/Morriar/item/10/profile"
system "curl -s {host}:{port}/user/Morriar/item/10/profile/settings"
-
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/not_found/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/user/:user/item/:item/*", new UserItem)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_glob_route do
+ var app = new App
+ app.use("/user/:user/item/:item/*", new UserItem)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_param_route is test_suite
+
+import pop_tests
import example_param_route
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleParamRoute
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/Morriar"
system "curl -s {host}:{port}//"
-
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/not_found/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/:user", new UserHome)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/:user", new UserHome)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_router is test_suite
+
+import pop_tests
import example_router
-import base_tests
-class HelloClient
- super ClientThread
+class TestExampleRouter
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}"
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/user"
system "curl -s {host}:{port}/user/"
system "curl -s {host}:{port}/user/profile"
-
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/user/not_found"
system "curl -s {host}:{port}/products/not_found"
- return null
end
-end
-
-var user_router = new Router
-user_router.use("/*", new UserLogger)
-user_router.use("/", new UserHome)
-user_router.use("/profile", new UserProfile)
-
-var app = new App
-app.use("/", new AppHome)
-app.use("/user", user_router)
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_router do
+ var user_router = new Router
+ user_router.use("/*", new UserLogger)
+ user_router.use("/", new UserHome)
+ user_router.use("/profile", new UserProfile)
+ var app = new App
+ app.use("/", new AppHome)
+ app.use("/user", user_router)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_session is test_suite
+
+import pop_tests
import example_session
-import base_tests
-class HelloClient
- super ClientThread
+class TestExampleSession
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/ -X POST"
-
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/user/not_found"
system "curl -s {host}:{port}/products/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/*", new SessionInit)
-app.use("/", new AppLogin)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/*", new SessionInit)
+ app.use("/", new AppLogin)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
-import base_tests
+module test_example_static is test_suite
+
+import pop_tests
import example_static
-class TestClient
- super ClientThread
+class TestExampleStatic
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/css/style.css"
system "curl -s {host}:{port}/js/app.js"
system "curl -s {host}:{port}/hello.html"
system "curl -s {host}:{port}/"
-
system "curl -s {host}:{port}/css/not_found.nit"
system "curl -s {host}:{port}/static/css/not_found.nit"
system "curl -s {host}:{port}/not_found.nit"
+ end
- return null
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new StaticHandler("../examples/static_files/public/"))
+ run_test(app)
end
end
-
-var app = new App
-app.use("/", new StaticHandler("../examples/static_files/public/"))
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
# See the License for the specific language governing permissions and
# limitations under the License.
-import base_tests
+module test_example_static_default is test_suite
+
+import pop_tests
import example_static_default
-class TestClient
- super ClientThread
+class TestExampleStaticDefault
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/css/style.css"
system "curl -s {host}:{port}/js/app.js"
system "curl -s {host}:{port}/hello.html"
system "curl -s {host}:{port}/"
-
system "curl -s {host}:{port}/css/not_found.nit"
system "curl -s {host}:{port}/static/css/not_found.nit"
system "curl -s {host}:{port}/not_found.nit"
+ end
- return null
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new StaticHandler("../examples/static_files/public/", "default.html"))
+ run_test(app)
end
end
-
-var app = new App
-app.use("/", new StaticHandler("../examples/static_files/public/", "default.html"))
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
# See the License for the specific language governing permissions and
# limitations under the License.
-import base_tests
+module test_example_static_multiple is test_suite
+
+import pop_tests
import example_static_multiple
-class TestClient
- super ClientThread
+class TestExampleStaticMultiple
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/css/style.css"
system "curl -s {host}:{port}/js/app.js"
system "curl -s {host}:{port}/hello.html"
system "curl -s {host}:{port}/"
-
system "curl -s {host}:{port}/static/css/style.css"
system "curl -s {host}:{port}/static/js/app.js"
system "curl -s {host}:{port}/static/hello.html"
system "curl -s {host}:{port}/static/"
-
system "curl -s {host}:{port}/css/not_found.nit"
system "curl -s {host}:{port}/static/css/not_found.nit"
system "curl -s {host}:{port}/not_found.nit"
+ end
- return null
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new StaticHandler("../examples/static_files/public/"))
+ app.use("/", new StaticHandler("../examples/static_files/files/"))
+ app.use("/static", new StaticHandler("../examples/static_files/public/"))
+ app.use("/static", new StaticHandler("../examples/static_files/files/"))
+ run_test(app)
end
end
-
-var app = new App
-app.use("/", new StaticHandler("../examples/static_files/public/"))
-app.use("/", new StaticHandler("../examples/static_files/files/"))
-app.use("/static", new StaticHandler("../examples/static_files/public/"))
-app.use("/static", new StaticHandler("../examples/static_files/files/"))
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
--- /dev/null
+# 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.
+
+# Popcorn testing services
+#
+# ## Blackbox testing
+#
+# Popcorn allows you to test your apps using nitunit blackbox testing.
+#
+# With blackbox testing you compare the output of your program with a result file.
+#
+# To get started with blackbox testing, create a nitunit test suite and imports
+# the `pop_tests` module.
+#
+# You then need to build the app that will be tested by nitunit as shown in the
+# `test_example_hello` method.
+# Calling `run_test` will automatically set the `host` and `port` used for testing.
+#
+# Redefine the `client_test` method to write your scenario.
+# Here we use `curl` to access some URI on the app.
+#
+# ~~~nitish
+# module test_example_hello is test_suite
+#
+# import pop_tests
+# import example_hello
+#
+# class TestExampleHello
+# super TestPopcorn
+#
+# fun test_example_hello do
+# var app = new App
+# app.use("/", new HelloHandler)
+# run_test(app)
+# end
+#
+# redef fun client_test do
+# system "curl -s {host}:{port}"
+# system "curl -s {host}:{port}/"
+# system "curl -s {host}:{port}///////////"
+# system "curl -s {host}:{port}/not_found"
+# system "curl -s {host}:{port}/not_found/not_found"
+# end
+# end
+# ~~~
+#
+# The blackbox testing needs a reference result file against wich the test output
+# will be compared.
+# Create your expected result file in `test_example_hello.sav/test_example_hello.res`.
+#
+# Test your app by running nitunit:
+#
+# ~~~bash
+# nitunit ./example_hello.nit
+# ~~~
+#
+# See `examples/hello_world` for the complete example.
+module pop_tests
+
+import test_suite
+import popcorn
+import pthreads
+
+redef class Sys
+
+ # Use localhost for testing
+ var test_host = "localhost"
+
+ # Return a new port for each instance
+ fun test_port: Int do
+ srand
+ return 10000+20000.rand
+ end
+end
+
+# Thread running the App to test.
+class AppThread
+ super Thread
+
+ # Host used by tested App.
+ var host: String
+
+ # Port used by tested App.
+ var port: Int
+
+ # App to test.
+ var app: App
+
+ redef fun main
+ do
+ # Hide testing concept to force nitcorn to actually run
+ "NIT_TESTING".setenv("false")
+ app.quiet = true
+ app.listen(host, port)
+ return null
+ end
+end
+
+# Thread running the test client.
+class ClientThread
+ super Thread
+
+ # Test suite to execute.
+ var test_suite: TestPopcorn
+
+ redef fun main do
+ test_suite.client_test
+ print ""
+ return null
+ end
+end
+
+# TestSuite for Popcorn blackbox testing.
+class TestPopcorn
+ super TestSuite
+
+ # Host used to run App.
+ var host: String = test_host
+
+ # Port used to run App.
+ var port: Int = test_port
+
+ # Run the test suite on the App.
+ fun run_test(app: App) do
+ var server = new AppThread(host, port, app)
+ server.start
+ 0.1.sleep
+
+ var client = new ClientThread(self)
+ client.start
+ client.join
+ 0.1.sleep
+
+ exit 0
+ end
+
+ # Redefine this method to implement your test scenario.
+ fun client_test do end
+
+ # Regex to catch and hide the port from the output to get consistent results
+ var host_re: Regex = "localhost:\[0-9\]+".to_re
+
+ # Execute a System function.
+ fun system(cmd: String, title: nullable String)
+ do
+ title = title or else cmd
+ title = title.replace(host_re, "localhost:*****")
+ print "\n[Client] {title}"
+ sys.system cmd
+ end
+end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2016 Alexandre Terrasa <alexandre@moz-code.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_popcorn is test_suite
+
+import pop_tests
+import popcorn
+
+class TestHandler
+ super Handler
+
+ var marker: String
+
+ redef fun get(req, res) do res.send marker
+end
+
+class TestPopcornRouter
+ super TestPopcorn
+
+ redef fun client_test do
+ system "curl -s {host}:{port}"
+ system "curl -s {host}:{port}/"
+ system "curl -s {host}:{port}/user"
+ system "curl -s {host}:{port}/user/"
+ system "curl -s {host}:{port}/user/settings"
+ system "curl -s {host}:{port}/products"
+ system "curl -s {host}:{port}/products/"
+ system "curl -s {host}:{port}/products/list"
+ system "curl -s {host}:{port}/not_found"
+ system "curl -s {host}:{port}/user/not_found"
+ system "curl -s {host}:{port}/products/not_found"
+ end
+
+ fun test_router do
+ var app = new App
+ app.use("/", new TestHandler("/"))
+ app.use("/about", new TestHandler("/about"))
+
+ var router1 = new App
+ router1.use("/", new TestHandler("/user"))
+ router1.use("/settings", new TestHandler("/user/settings"))
+ app.use("/user", router1)
+
+ var router2 = new App
+ router2.use("/", new TestHandler("/products"))
+ router2.use("/list", new TestHandler("/products/list"))
+ app.use("/products", router2)
+
+ run_test(app)
+ end
+end
+
+class TestPopcornRoutes
+ super TestPopcorn
+
+ redef fun client_test do
+ system "curl -s {host}:{port}"
+ system "curl -s {host}:{port}/"
+ system "curl -s {host}:{port}/misc"
+ system "curl -s {host}:{port}/misc/foo"
+ system "curl -s {host}:{port}/misc/foo/bar"
+ system "curl -s {host}:{port}/misc/foo/baz"
+ system "curl -s {host}:{port}/user"
+ system "curl -s {host}:{port}/user/"
+ system "curl -s {host}:{port}/user/id"
+ system "curl -s {host}:{port}/user/id/profile"
+ system "curl -s {host}:{port}/user/id/misc/foo"
+ system "curl -s {host}:{port}/user/id/misc/foo/bar"
+ system "curl -s {host}:{port}/user/id/misc/foo/bar/baz"
+ system "curl -s {host}:{port}/not_found"
+ system "curl -s {host}:{port}/user/id/not_found"
+ end
+
+ fun test_routes do
+ var app = new App
+ app.use("/", new TestHandler("/"))
+ app.use("/user", new TestHandler("/user"))
+ app.use("/misc/*", new TestHandler("/misc/everything"))
+ app.use("/user/:id", new TestHandler("/user/id"))
+ app.use("/user/:id/profile", new TestHandler("/user/id/profile"))
+ app.use("/user/:id/misc/*", new TestHandler("/user/id/misc/everything"))
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
+++ /dev/null
-# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.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.
-
-all: tests
-
-check: clean
- ./tests.sh
-
-clean:
- rm -rf out/
+++ /dev/null
-# 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.
-
-import popcorn
-import pthreads
-
-redef class Sys
- var test_host = "localhost"
-
- # Return a new port for each instance
- fun test_port: Int do
- srand
- return 10000+20000.rand
- end
-end
-
-class AppThread
- super Thread
-
- var host: String
- var port: Int
- var app: App
-
- redef fun main
- do
- # Hide testing concept to force nitcorn to actually run
- "NIT_TESTING".setenv("false")
- app.quiet = true
- app.listen(host, port)
- return null
- end
-end
-
-class ClientThread
- super Thread
-
- var host: String
- var port: Int
-
- redef fun main do return null
-
- # Regex to catch and hide the port from the output to get consistent results
- var host_re: Regex = "localhost:\[0-9\]+".to_re
-
- fun system(cmd: String, title: nullable String)
- do
- title = title or else cmd
- title = title.replace(host_re, "localhost:*****")
- print "\n[Client] {title}"
- sys.system cmd
- end
-end
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2016 Alexandre Terrasa <alexandre@moz-code.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.
-
-import base_tests
-
-class TestHandler
- super Handler
-
- var marker: String
-
- redef fun get(req, res) do res.send marker
-end
-
-class HelloClient
- super ClientThread
-
- redef fun main do
- system "curl -s {host}:{port}"
- system "curl -s {host}:{port}/"
- system "curl -s {host}:{port}/user"
- system "curl -s {host}:{port}/user/"
- system "curl -s {host}:{port}/user/settings"
- system "curl -s {host}:{port}/products"
- system "curl -s {host}:{port}/products/"
- system "curl -s {host}:{port}/products/list"
-
- system "curl -s {host}:{port}/not_found"
- system "curl -s {host}:{port}/user/not_found"
- system "curl -s {host}:{port}/products/not_found"
- return null
- end
-end
-
-var app = new App
-app.use("/", new TestHandler("/"))
-app.use("/about", new TestHandler("/about"))
-
-var router1 = new App
-router1.use("/", new TestHandler("/user"))
-router1.use("/settings", new TestHandler("/user/settings"))
-app.use("/user", router1)
-
-var router2 = new App
-router2.use("/", new TestHandler("/products"))
-router2.use("/list", new TestHandler("/products/list"))
-app.use("/products", router2)
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2016 Alexandre Terrasa <alexandre@moz-code.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.
-
-import base_tests
-
-class TestHandler
- super Handler
-
- var marker: String
-
- redef fun get(req, res) do res.send marker
-end
-
-class HelloClient
- super ClientThread
-
- redef fun main do
- system "curl -s {host}:{port}"
- system "curl -s {host}:{port}/"
-
- system "curl -s {host}:{port}/misc"
- system "curl -s {host}:{port}/misc/foo"
- system "curl -s {host}:{port}/misc/foo/bar"
- system "curl -s {host}:{port}/misc/foo/baz"
-
- system "curl -s {host}:{port}/user"
- system "curl -s {host}:{port}/user/"
- system "curl -s {host}:{port}/user/id"
- system "curl -s {host}:{port}/user/id/profile"
- system "curl -s {host}:{port}/user/id/misc/foo"
- system "curl -s {host}:{port}/user/id/misc/foo/bar"
- system "curl -s {host}:{port}/user/id/misc/foo/bar/baz"
-
- system "curl -s {host}:{port}/not_found"
- system "curl -s {host}:{port}/user/id/not_found"
- return null
- end
-end
-
-var app = new App
-app.use("/", new TestHandler("/"))
-app.use("/user", new TestHandler("/user"))
-app.use("/misc/*", new TestHandler("/misc/everything"))
-app.use("/user/:id", new TestHandler("/user/id"))
-app.use("/user/:id/profile", new TestHandler("/user/id/profile"))
-app.use("/user/:id/misc/*", new TestHandler("/user/id/misc/everything"))
-
-var host = test_host
-var port = test_port
-
-# First, launch a server in the background
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-# Then, launch a client running test requests
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-# Force quit the server
-exit 0
+++ /dev/null
-#!/bin/bash
-
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2016 Alexandre Terrasa <alexandre@moz-code.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.
-
-BIN=../bin
-OUT=./out
-RES=./res
-
-NITC=../../../bin/nitc
-
-compile() {
- local test="$1"
- $NITC $test.nit -o $OUT/$test.bin 1>&2 2> $OUT/$test.cmp_err
-}
-
-test_prog()
-{
- local test="$1"
-
- chmod +x $OUT/$test.bin 2> $OUT/$test.err
- $OUT/$test.bin > $OUT/$test.res 2> $OUT/$test.err
-
- diff $OUT/$test.res $RES/$test.res > $OUT/$test.diff 2> /dev/null
-}
-
-# return
-# 0 if the sav not exists
-# 1 if the file does match
-# 2 if the file does not match
-check_result() {
- local test="$1"
-
- if [ -s "$OUT/$test.cmp_err" ]; then
- return 0
- elif [ -s "$OUT/$test.err" ]; then
- return 1
- elif [ ! -r "$RES/$test.res" ]; then
- return 2
- elif [ -s "$OUT/$test.diff" ]; then
- return 3
- else
- return 4
- fi
-}
-
-echo "Testing..."
-echo ""
-
-rm -rf $OUT 2>/dev/null
-mkdir $OUT 2>/dev/null
-
-all=0
-ok=0
-ko=0
-sk=0
-
-for file in `ls test_*.nit`; do
- ((all++))
- test="${file%.*}"
- echo -n "* $test: "
-
- compile $test
- test_prog $test
- check_result $test
-
- case "$?" in
- 0)
- echo "compile error (cat $OUT/$test.cmp_err)"
- ((ko++))
- ;;
- 1)
- echo "error (cat $OUT/$test.cmp_err)"
- ((ko++))
- ;;
- 2)
- echo "skip ($test.res not found)"
- ((sk++))
- continue;;
- 3)
- echo "error (diff $OUT/$test.res $RES/$test.res)"
- ((ko++))
- ;;
- 4)
- echo "success"
- ((ok++))
- ;;
-
- esac
-done
-echo ""
-echo "==> success $ok/$all ($ko tests failed, $sk skipped)"
-
-# return result
-test "$ok" == "$all"
## Working with `TestSuites`
-TestSuites are Nit files that define a set of TestCases for a particular module.
+TestSuites are Nit modules that define a set of TestCases.
-The test suite must be called `test_` followed by the name of the module to test.
-So for the module `foo.nit` the test suite will be called `test_foo.nit`.
+A test suite is a module that uses the annotation `is test_suite`.
+
+It is common that a test suite focuses on testing a single module.
+In this case, the name of the test_suite is often `test_foo.nit` where `foo.nit` is the tested module.
The structure of a test suite is the following:
~~~~
# test suite for module `foo`
-module test_foo
+module test_foo is test_suite
+
+import test_suite
import foo # can be intrude to test private things
+
class TestFoo
+ super TestSuite
+
# test case for `foo::Foo::baz`
fun test_baz do
var subject = new Foo
$ nitunit foo.nit
-`nitunit` will execute a test for each method named `test_*` in a class named `Test*`
-so multiple tests can be executed for a single method:
+`nitunit` will execute a test for each method named `test_*` in a class
+subclassing `TestSuite` so multiple tests can be executed for a single method:
~~~~
class TestFoo
+ super TestSuite
+
fun test_baz_1 do
var subject = new Foo
assert subject.baz(1, 2) == 3
~~~
module test_mod is test_suite
+
class TestFoo
+ super TestSuite
+
fun test_bar do
print "Hello!"
end
## Configuring TestSuites
-`TestSuites` also provide methods to configure the test run:
+`TestSuite`s also provide methods to configure the test run:
`before_test` and `after_test`: methods called before/after each test case.
They can be used to factorize repetitive tasks:
~~~~
class TestFoo
+ super TestSuite
var subject: Foo
# Mandatory empty init
init do end
Examples: `TestFoo`, `TestFoo*`, `TestFoo::test_foo`, `TestFoo::test_foo*`, `test_foo`, `test_foo*`
-### `-t`, `--target-file`
-Specify test suite location.
-
### `--autosav`
Automatically create/update .res files for black box testing.
if decl != null then
var decl_name = decl.n_name.n_id.text
if decl_name != mmodule.name then
- error(decl.n_name, "Error: module name mismatch; declared {decl_name} file named {mmodule.name}.")
+ warning(decl.n_name, "module-name-mismatch", "Error: module name mismatch; declared {decl_name} file named {mmodule.name}.")
end
end
var toolcontext = new ToolContext
-toolcontext.option_context.add_option(toolcontext.opt_full, toolcontext.opt_output, toolcontext.opt_dir, toolcontext.opt_noact, toolcontext.opt_pattern, toolcontext.opt_file, toolcontext.opt_autosav, toolcontext.opt_gen_unit, toolcontext.opt_gen_force, toolcontext.opt_gen_private, toolcontext.opt_gen_show, toolcontext.opt_nitc)
+toolcontext.option_context.add_option(toolcontext.opt_full, toolcontext.opt_output, toolcontext.opt_dir, toolcontext.opt_noact, toolcontext.opt_pattern, toolcontext.opt_autosav, toolcontext.opt_gen_unit, toolcontext.opt_gen_force, toolcontext.opt_gen_private, toolcontext.opt_gen_show, toolcontext.opt_nitc)
toolcontext.tooldescription = "Usage: nitunit [OPTION]... <file.nit>...\nExecutes the unit tests from Nit source files."
toolcontext.process_options(args)
print "Option --pattern cannot be used with --gen-suite"
exit(0)
end
- if toolcontext.opt_file.value != null then
- print "Option --target-file cannot be used with --gen-suite"
- exit(0)
- end
else
if toolcontext.opt_gen_force.value then
print "Option --force must be used with --gen-suite"
for m in mmodules do
page.add modelbuilder.test_markdown(m)
- page.add modelbuilder.test_unit(m)
+ var ts = modelbuilder.test_unit(m)
+ if ts != null then page.add ts
end
var file = toolcontext.opt_output.value
if mmodule != null then
opts.add "-I {mmodule.filepath.dirname}"
end
- var cmd = "{nitc} --ignore-visibility --no-color '{file}' {opts.join(" ")} >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
+ var cmd = "{nitc} --ignore-visibility --no-color -q '{file}' {opts.join(" ")} >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
var res = toolcontext.safe_exec(cmd)
return res
end
private import annotation
redef class ToolContext
- # -- target-file
- var opt_file = new OptionString("Specify test suite location", "-t", "--target-file")
# --pattern
var opt_pattern = new OptionString("Only run test case with name that match pattern", "-p", "--pattern")
# --autosav
# `ModelBuilder` used to parse test files.
var mbuilder: ModelBuilder
- # Parse a file and return the contained `MModule`.
- private fun parse_module_unit(file: String): nullable MModule do
- var mmodule = mbuilder.parse([file]).first
- if mbuilder.get_mmodule_annotation("test_suite", mmodule) == null then return null
- mbuilder.run_phases
- return mmodule
- end
-
- # Compile and execute the test suite for a NitUnit `file`.
- fun test_module_unit(file: String): nullable TestSuite do
+ # Compile and execute `mmodule` as a test suite.
+ fun test_module_unit(mmodule: MModule): TestSuite do
var toolcontext = mbuilder.toolcontext
- var mmodule = parse_module_unit(file)
- # is the module a test_suite?
- if mmodule == null then return null
var suite = new TestSuite(mmodule, toolcontext)
# method to execute before all tests in the module
var before_module = mmodule.before_test
return
end
var include_dir = module_file.filename.dirname
- var cmd = "{nitc} --no-color '{file}.nit' -I {include_dir} -o '{file}.bin' > '{file}.out' 2>&1 </dev/null"
+ var cmd = "{nitc} --no-color -q '{file}.nit' -I {include_dir} -o '{file}.bin' > '{file}.out' 2>&1 </dev/null"
var res = toolcontext.safe_exec(cmd)
var f = new FileReader.open("{file}.out")
var msg = f.read_all
redef class MClassDef
# Is the class a TestClass?
- # i.e. begins with "Test"
+ # i.e. is a subclass of `TestSuite`
private fun is_test: Bool do
var in_hierarchy = self.in_hierarchy
if in_hierarchy == null then return false
# Number of failed tests.
var failed_tests = 0
- # Run NitUnit test file for mmodule (if exists).
- fun test_unit(mmodule: MModule): HTMLTag do
- var ts = new HTMLTag("testsuite")
- toolcontext.info("nitunit: test-suite test_{mmodule}", 2)
- var f = toolcontext.opt_file.value
- var test_file = "test_{mmodule.name}.nit"
- if f != null then
- test_file = f
- else if not test_file.file_exists then
- var module_file = mmodule.location.file
- if module_file == null then
- toolcontext.info("Skip test for {mmodule}, no file found", 2)
- return ts
- end
- var include_dir = module_file.filename.dirname
- test_file = "{include_dir}/{test_file}"
- end
- if not test_file.file_exists then
- toolcontext.info("Skip test for {mmodule}, no file {test_file} found", 2)
- return ts
- end
+ # Run NitUnit test suite for `mmodule` (if it is one).
+ fun test_unit(mmodule: MModule): nullable HTMLTag do
+ # is the module a test_suite?
+ if get_mmodule_annotation("test_suite", mmodule) == null then return null
+ toolcontext.info("nitunit: test-suite {mmodule}", 2)
+
var tester = new NitUnitTester(self)
- var res = tester.test_module_unit(test_file)
- if res == null then
- toolcontext.info("Skip test for {mmodule}, no test suite found", 2)
- return ts
- end
+ var res = tester.test_module_unit(mmodule)
return res.to_xml
end
end
-test_nitunit.nit --no-color -o $WRITE
+test_nitunit.nit test_test_nitunit.nit --no-color -o $WRITE
test_nitunit.nit --gen-suite --only-show
test_nitunit.nit --gen-suite --only-show --private
test_nitunit2.nit --no-color -o $WRITE
[OK] test_test_nitunit$TestX$test_foo2
-Docunits: Entities: 27; Documented ones: 4; With nitunits: 4; Failures: 3
+Docunits: Entities: 34; Documented ones: 6; With nitunits: 4; Failures: 3
Test suites: Classes: 1; Test Cases: 3; Failures: 1
[FAILURE] 4/7 tests failed.
`nitunit.out` is not removed for investigation.
</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="test_nitunit::X::foo"><failure>Compilation error in nitunit.out/test_nitunit-3.nit</failure><system-err>nitunit.out/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
</system-err><system-out>assert undefined_identifier
</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="test_nitunit::X::foo1"><failure>Syntax Error: unexpected operator '!'.</failure><system-out>assert !@#$%^&*()
-</system-out></testcase></testsuite><testsuite package="test_test_nitunit"><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo"><system-err></system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo1"><error>Runtime Error in file nitunit.out/gen_test_test_nitunit.nit</error><system-err>Runtime error: Assert failed (test_test_nitunit.nit:39)
+</system-out></testcase></testsuite><testsuite package="test_test_nitunit::test_test_nitunit"></testsuite><testsuite package="test_test_nitunit"><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo"><system-err></system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo1"><error>Runtime Error in file nitunit.out/gen_test_test_nitunit.nit</error><system-err>Runtime error: Assert failed (test_test_nitunit.nit:39)
</system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo2"><system-err></system-err></testcase></testsuite></testsuites>
\ No newline at end of file
</system-out></testcase><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::foo3"><system-err></system-err><system-out>var a = 1
assert a == 1
assert a == 1
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
<testsuites><testsuite package="test_doc2::test_doc2"><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo1"><system-err></system-err><system-out>assert true # tested
</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo2"><system-err></system-err><system-out>assert true # tested
</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo3"><system-err></system-err><system-out>assert true # tested
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
assert true
</system-out></testcase><testcase classname="nitunit.test_nitunit3>" name="<group>#2"><failure>Syntax Error: unexpected malformed character '\].</failure><system-out>;'\][]
</system-out></testcase></testsuite><testsuite package="test_nitunit3::test_nitunit3"><testcase classname="nitunit.test_nitunit3::test_nitunit3.<module>" name="<module>"><system-err></system-err><system-out>assert true
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
<testsuites><testsuite package="test_doc3::test_doc3"><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo1"><failure>Syntax Error: unexpected identifier 'garbage'.</failure><system-out> *garbage*
</system-out></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo2"><failure>Syntax Error: unexpected identifier 'garbage'.</failure><system-out>*garbage*
</system-out></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo3"><failure>Syntax Error: unexpected identifier 'garbage'.</failure><system-out>*garbage*
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
After Test
+==== Test-suite of module test_nitunit4::test_nitunit4_base | tests: 0
+==== Test-suite of module test_nitunit4::test_nitunit4_base | tests: 0
+
Docunits: Entities: 13; Documented ones: 0; With nitunits: 0
-Test suites: Classes: 1; Test Cases: 4; Failures: 3
+Test suites: Classes: 2; Test Cases: 4; Failures: 3
[FAILURE] 3/4 tests failed.
`nitunit.out` is not removed for investigation.
-<testsuites><testsuite package="test_nitunit4>"></testsuite><testsuite package="test_nitunit4::nitunit4"></testsuite><testsuite package="test_nitunit4"><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_foo"><error>Runtime Error in file nitunit.out/gen_test_nitunit4.nit</error><system-err>Before Test
+<testsuites><testsuite package="test_nitunit4>"></testsuite><testsuite package="test_nitunit4::nitunit4"></testsuite><testsuite package="test_nitunit4::test_nitunit4"></testsuite><testsuite package="test_nitunit4"><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_foo"><error>Runtime Error in file nitunit.out/gen_test_nitunit4.nit</error><system-err>Before Test
Tested method
After Test
Runtime error: Assert failed (test_nitunit4/test_nitunit4_base.nit:31)
</system-err></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_sav_conflict"><error>Conflicting expected output: test_nitunit4/test_nitunit4.sav/test_sav_conflict.res, test_nitunit4/sav/test_sav_conflict.res and test_nitunit4/test_sav_conflict.res all exist</error><system-err>Before Test
Tested method
After Test
-</system-err></testcase></testsuite><testsuite package="test_nitunit4::test_nitunit4"></testsuite><testsuite></testsuite><testsuite package="test_nitunit4::test_nitunit4_base"></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-err></testcase></testsuite><testsuite package="test_nitunit4::test_nitunit4_base"></testsuite><testsuite package="test_nitunit4_base"></testsuite></testsuites>
\ No newline at end of file