Merge: curl: fix concurrent requests and intro shortcut services for scripts
authorJean Privat <jean@pryen.org>
Thu, 21 Feb 2019 23:38:01 +0000 (18:38 -0500)
committerJean Privat <jean@pryen.org>
Thu, 21 Feb 2019 23:38:01 +0000 (18:38 -0500)
This PR brings 2 main changes:

* The handle to a Curl request is now kept by the `CurlRequest` instances, instead of being shared by all requests. This makes it possible to execute concurrent HTTP requests.

* Intro two new services on `Text` to execute simple HTTP requests. While these new services are useful to simple scripts, if more control is needed you should still use `CurlHTTPRequest`.

  `Text::http_get` makes a GET request and returns the response body.

  `Text::http_download` makes a GET request and saves the response body to a file.

Pull-Request: #2731
Reviewed-by: Jean Privat <jean@pryen.org>

38 files changed:
.gitlab-ci.yml [new file with mode: 0644]
Makefile
c_src/Makefile
contrib/model_viewer/README.md
examples/calculator/README.md
lib/app/README.md
lib/core/collection/abstract_collection.nit
lib/core/collection/circular_array.nit
lib/core/collection/union_find.nit
lib/core/kernel.nit
lib/core/text/abstract_text.nit
lib/core/text/fixed_ints_text.nit
lib/gamnit/README.md
lib/github/api.nit
lib/libevent/libevent.nit
lib/libevent/libevent_example.nit [new file with mode: 0644]
lib/libevent/libevent_test.nit [new file with mode: 0644]
lib/libevent/package.ini
lib/nitcorn/reactor.nit
lib/perfect_hashing/perfect_hashing.nit
lib/popcorn/pop_repos.nit
lib/serialization/README.md
lib/trees/bintree.nit
misc/docker/ci/Dockerfile [new file with mode: 0644]
misc/docker/ci/README.md [new file with mode: 0644]
src/compiler/abstract_compiler.nit
src/testing/testing_doc.nit
tests/base_autocast.nit
tests/gitlab_ci.skip [new file with mode: 0644]
tests/sav/base_autocast_alt2.res
tests/sav/error_class_glob.res
tests/sav/gitlab_ci/simple_file_server.res [new file with mode: 0644]
tests/sav/libevent_test.res [new file with mode: 0644]
tests/sav/nitunit_args1.res
tests/sav/nitunit_args6.res
tests/sav/simple_file_server.res
tests/test_nitunit.nit
tests/tests.sh

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644 (file)
index 0000000..1a70ece
--- /dev/null
@@ -0,0 +1,333 @@
+image: nitlang/nit-ci
+
+cache:
+  paths:
+    - .ccache
+  key: "$CI_JOB_NAME"
+
+stages:
+  - build
+  - test
+  - more_test
+  - deploy
+
+before_script:
+  - date
+  - export CCACHE_DIR=$PWD/.ccache
+  - export PATH=$PWD/bin:$PATH
+  - pwd
+  - ccache -s
+  - ccache -M 500M
+  - type -a nitc nitdoc || true # is there some nit tools?
+  - "> status.txt"
+
+after_script:
+  - export CCACHE_DIR=$PWD/.ccache
+  - ccache -s
+  - git status --ignored
+  - date
+  - tail status.txt
+
+# BASIC JOBS ########################################################
+
+sanity_checks:
+  stage: build
+  script:
+    - misc/jenkins/checkwhitespaces.sh | tee -a status.txt
+    - misc/jenkins/checksignedoffby.sh | tee -a status.txt
+    - misc/jenkins/checklicense.sh | tee -a status.txt
+
+build_tools:
+  stage: build
+  script:
+    - make 2>> status.txt
+    - nitc --version
+    - misc/jenkins/check_manpages.sh
+    - "{ cd tests && ./tests.sh base_sim*.nit ../src/nitlight.nit; }"
+    - nitunit -v lib/core
+  artifacts:
+    paths:
+      - bin/*
+      - c_src/nitc
+      - src/version.nit
+      - src/nitc_0
+      - nitunit.xml*
+      - tests/*.xml*
+    when: always
+    reports:
+      junit:
+        - tests/*.xml
+        - nitunit.xml
+
+test_some:
+  stage: test
+  dependencies:
+    - build_tools
+  script:
+    - cd tests
+    - ./search_tests_git.sh origin/master HEAD > list
+    - ./testall.sh `cat list` | tee log.txt
+    - grep -v '=>' log.txt > ../status.txt || true
+  artifacts:
+    paths:
+      - tests/errlist
+      - tests/*.xml
+    when: always
+    reports:
+      junit: tests/*.xml
+
+nitunit_some:
+  stage: test
+  dependencies:
+    - build_tools
+  script:
+    - git diff --name-only origin/master..HEAD -- "*.nit" "*.res" "README.*" | grep -v "^tests/" > list0.txt
+    - xargs nitls -pP < list0.txt > list.txt
+    - xargs nitunit < list.txt
+  artifacts:
+    paths:
+      - nitunit.xml*
+    when: always
+    reports:
+      junit:
+        - nitunit.xml
+
+nitpick_full:
+  stage: test
+  dependencies:
+    - build_tools
+  script:
+    - nitls lib src examples contrib
+    - nitls -Pp lib src examples | grep -v -f tests/gitlab_ci.skip > list.txt # filter what is skipped by tests.sh
+    - xargs nitpick < list.txt
+
+# TEST FULL #########################################################
+
+test_full_nitcs:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - cd tests
+    - ./testfull.sh | tee log.txt
+    - grep -v '=>' log.txt > ../status.txt || true
+  artifacts:
+    paths:
+      - tests/errlist
+      - tests/*.xml*
+      - tests/out/*.res
+      - tests/out/*.log
+    when: always
+    reports:
+      junit: tests/*.xml
+
+test_full_niti:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - cd tests
+    - ./testfull.sh --engine niti | tee log.txt
+    - grep -v '=>' log.txt > ../status.txt || true
+  artifacts:
+    paths:
+      - tests/errlist
+      - tests/*.xml*
+      - tests/out/*.res
+      - tests/out/*.log
+    when: always
+    reports:
+      junit: tests/*.xml
+
+test_full_nitcg:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - cd tests
+    - ./testfull.sh --engine nitcg | tee log.txt
+    - grep -v '=>' log.txt > ../status.txt || true
+  artifacts:
+    paths:
+      - tests/errlist
+      - tests/*.xml*
+      - tests/out/*.res
+      - tests/out/*.log
+    when: always
+    reports:
+      junit: tests/*.xml
+
+test_full_nitce:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - cd tests
+    - ./testfull.sh --engine nitce | tee log.txt
+    - grep -v '=>' log.txt > ../status.txt || true
+  artifacts:
+    paths:
+      - tests/errlist
+      - tests/*.xml*
+      - tests/out/*.res
+      - tests/out/*.log
+    when: always
+    reports:
+      junit: tests/*.xml
+
+test_full_nitcsg:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - cd tests
+    - ./testfull.sh --engine nitcsg | tee log.txt
+    - grep -v '=>' log.txt > ../status.txt || true
+  artifacts:
+    paths:
+      - tests/errlist
+      - tests/*.xml*
+      - tests/out/*.res
+      - tests/out/*.log
+    when: always
+    reports:
+      junit: tests/*.xml
+
+# LIB, CONTRIB AND OOT ##############################################
+
+nitunit_lib:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - nitls -Pp lib | grep -v -f tests/gitlab_ci.skip > list.txt # filter what is skipped by tests.sh
+    - xargs nitunit -v < list.txt| tee log.txt
+    - grep -e KO log.txt > status.txt || true
+    - tail -3 log.txt >> status.txt
+  artifacts:
+    paths:
+      - nitunit.xml*
+    when: always
+    reports:
+      junit:
+        - nitunit.xml
+
+nitunit_src:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - nitls -Pp src examples | grep -v -f tests/gitlab_ci.skip > list.txt # filter what is skipped by tests.sh
+    - xargs nitunit -v < list.txt| tee log.txt
+    - grep -e KO log.txt > status.txt || true
+    - tail -3 log.txt >> status.txt
+  artifacts:
+    paths:
+      - nitunit.xml*
+    when: always
+    reports:
+      junit:
+        - nitunit.xml
+
+test_contribs:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - misc/jenkins/check_contrib.sh all check
+    - grep 'error message' *.xml > status.txt || true
+    - test ! -s status.txt # no lines, no errors
+  allow_failure: true
+
+build_oot:
+  stage: more_test
+  dependencies:
+    - build_more_tools
+  script:
+    - cd contrib
+    - ./oot.sh all
+    - grep 'error message' *.xml > ../status.txt || true
+    - test ! -s ../status.txt # no lines, no errors
+  allow_failure: true
+
+# MISC ##############################################################
+
+bootstrap_full:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - cd src
+    - ./full_bootstrap
+    - ./ncall.sh
+
+bench_fast:
+  stage: more_test
+  dependencies:
+    - build_tools
+  script:
+    - cd benchmarks
+    - ./bench_engines.sh --fast --fast --html options
+    - grep -B1 'error message' *.xml | grep testcase > ../status.txt || true
+  artifacts:
+    paths:
+      - benchmarks/*.html
+      - benchmarks/*.png
+      - benchmarks/*.dat
+      - benchmarks/*.gnu
+    when: always
+  allow_failure: true
+
+
+# MORE TOOLS ########################################################
+
+build_more_tools:
+  stage: test
+  dependencies:
+    - build_tools
+  script:
+    - make more
+    - make -C "contrib/nitcc"
+  artifacts:
+    paths:
+      - bin/*
+      - c_src/nitc
+      - src/version.nit
+      - src/nitc_0
+
+build_doc:
+  stage: more_test
+  dependencies:
+    - build_more_tools
+  script:
+    - nitls -r -t .
+    - nitdoc -d nitdoc.out --keep-going lib src
+  artifacts:
+    paths:
+      - nitdoc.out
+
+build_catalog:
+  stage: more_test
+  dependencies:
+    - build_more_tools
+  script:
+    - misc/jenkins/check_contrib.sh pre-build
+    - cd contrib
+    - ./oot.sh update
+    - ./oot.sh pre-build
+    - cd ..
+    - nitcatalog -d catalog.out lib/ examples/ contrib/ contrib/oot/
+  dependencies:
+    - build_more_tools
+  artifacts:
+    paths:
+      - catalog.out
+
+.test_macos:
+  script:
+    - uname
+    - pwd
+    - ls /
+  stage: build
+  tags:
+    - macos
index 3557372..4f4f71b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -83,6 +83,8 @@ clean:
        cd src; make clean
        cd tests; make clean
        cd share/man; make clean
-       for directory in $(extras); do \
-               (cd "$$directory" && $(MAKE) clean); \
+       -for directory in $(extras); do \
+               (echo "CLEANING $$directory" && cd "$$directory" && $(MAKE) clean); \
        done
+       @echo ""
+       @echo "Nit was succesfully cleaned."
\ No newline at end of file
index abffff8..87d394d 100644 (file)
@@ -576,4 +576,4 @@ nitc: nitc__nith.classes.1.o nitc__nith.classes.2.o nitc__nith.classes.3.o nitc_
        $(CC) $(LDFLAGS) -o 'nitc' nitc__nith.classes.1.o nitc__nith.classes.2.o nitc__nith.classes.3.o nitc__nith.classes.4.o nitc__nith.classes.5.o nitc__nith.classes.6.o nitc__nith.main.1.o nitc__nith.sep.1.o nitc__modelize_property.sep.1.o nitc__modelize_property.sep.2.o nitc__modelize_property.sep.3.o nitc__modelize_class.sep.1.o nitc__modelbuilder.sep.1.o nitc__loader.sep.1.o nitc__loader.sep.2.o nitc__modelbuilder_base.sep.1.o nitc__model.sep.1.o nitc__model.sep.2.o nitc__model.sep.3.o nitc__mmodule.sep.1.o nitc__mpackage.sep.1.o nitc__model_base.sep.1.o nitc__location.sep.1.o core__ropes.sep.1.o core__flat.sep.1.o core__flat.sep.2.o core__abstract_text.sep.1.o core__native.sep.1.o core__kernel.sep.1.o core__math.sep.1.o core__abstract_collection.sep.1.o core__list.sep.1.o core__array.sep.1.o core__circular_array.sep.1.o core__sorter.sep.1.o core__hash_collection.sep.1.o core__fixed_ints.sep.1.o core__string_search.sep.1.o core__fixed_ints_text.sep.1.o core__environ.sep.1.o core__file.sep.1.o core__stream.sep.1.o core__error.sep.1.o core__bytes.sep.1.o core__utf8.sep.1.o core__time.sep.1.o core__exec.sep.1.o more_collections.sep.1.o poset.sep.1.o nitc__mdoc.sep.1.o ordered_tree.sep.1.o nitc__toolcontext.sep.1.o opts.sep.1.o nitc__version.sep.1.o template.sep.1.o nitc__parser.sep.1.o nitc__parser.sep.2.o nitc__parser.sep.3.o nitc__parser.sep.4.o nitc__parser.sep.5.o nitc__parser.sep.6.o nitc__parser.sep.7.o nitc__parser_prod.sep.1.o nitc__parser_prod.sep.2.o nitc__parser_prod.sep.3.o nitc__parser_prod.sep.4.o nitc__parser_prod.sep.5.o nitc__parser_prod.sep.6.o nitc__lexer.sep.1.o nitc__parser_nodes.sep.1.o nitc__lexer_work.sep.1.o nitc__tables.sep.1.o nitc__parser_work.sep.1.o ini.sep.1.o nitc__phase.sep.1.o nitc__annotation.sep.1.o nitc__literal.sep.1.o nitc__transform.sep.1.o nitc__astbuilder.sep.1.o nitc__typing.sep.1.o nitc__typing.sep.2.o nitc__typing.sep.3.o nitc__local_var_init.sep.1.o nitc__flow.sep.1.o nitc__scope.sep.1.o nitc__astvalidation.sep.1.o nitc__auto_super_init.sep.1.o nitc__rapid_type_analysis.sep.1.o csv.sep.1.o nitc__separate_erasure_compiler.sep.1.o nitc__separate_erasure_compiler.sep.2.o nitc__separate_compiler.sep.1.o nitc__separate_compiler.sep.2.o nitc__separate_compiler.sep.3.o nitc__separate_compiler.sep.4.o nitc__separate_compiler.sep.5.o nitc__separate_compiler.sep.6.o nitc__abstract_compiler.sep.1.o nitc__abstract_compiler.sep.2.o nitc__abstract_compiler.sep.3.o nitc__abstract_compiler.sep.4.o nitc__abstract_compiler.sep.5.o nitc__abstract_compiler.sep.6.o nitc__abstract_compiler.sep.7.o nitc__platform.sep.1.o nitc__c_tools.sep.1.o nitc__mixin.sep.1.o counter.sep.1.o nitc__coloring.sep.1.o nitc__light_only.sep.1.o nitc__light.sep.1.o nitc__light_ffi.sep.1.o nitc__nitni_utilities.sep.1.o nitc__nitni_base.sep.1.o nitc__light_ffi_base.sep.1.o nitc__extern_classes.sep.1.o nitc__light_c.sep.1.o nitc__nith.types.1.o nitc__nith.types.2.o nitc__nith.types.3.o nitc__nith.types.4.o nitc__nith.types.5.o nitc__nith.types.6.o nitc__nith.types.7.o nitc__nith.types.8.o nitc__nith.types.9.o nitc__nith.types.10.o nitc__nith.types.11.o nitc__nith.types.12.o nitc__nith.types.13.o nitc__nith.types.14.o nitc__nith.types.15.o nitc__nith.types.16.o nitc__nith.types.17.o nitc__nith.types.18.o nitc__nith.types.19.o nitc__nith.types.20.o nitc__nith.types.21.o nitc__nith.types.22.o nitc__nith.types.23.o nitc__nith.types.24.o nitc__nith.types.25.o nitc__nith.types.26.o nitc__nith.types.27.o nitc__nith.types.28.o nitc__nith.types.29.o nitc__nith.types.30.o nitc__nith.types.31.o nitc__nith.types.32.o nitc__nith.types.33.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o core__abstract_text._ffi.extern.o core__abstract_text._nitni.extern.o core__native._ffi.extern.o core__native._nitni.extern.o core__kernel._ffi.extern.o core__kernel._nitni.extern.o core__math._ffi.extern.o core__math._nitni.extern.o core__fixed_ints_text._ffi.extern.o core__fixed_ints_text._nitni.extern.o core__environ._ffi.extern.o core__environ._nitni.extern.o core__file._ffi.extern.o core__file._nitni.extern.o core__time._ffi.extern.o core__time._nitni.extern.o core__exec._ffi.extern.o core__exec._nitni.extern.o $(LDLIBS) `pkg-config --libs bdw-gc`
 
 clean:
-       rm nitc__nith.classes.1.o nitc__nith.classes.2.o nitc__nith.classes.3.o nitc__nith.classes.4.o nitc__nith.classes.5.o nitc__nith.classes.6.o nitc__nith.main.1.o nitc__nith.sep.1.o nitc__modelize_property.sep.1.o nitc__modelize_property.sep.2.o nitc__modelize_property.sep.3.o nitc__modelize_class.sep.1.o nitc__modelbuilder.sep.1.o nitc__loader.sep.1.o nitc__loader.sep.2.o nitc__modelbuilder_base.sep.1.o nitc__model.sep.1.o nitc__model.sep.2.o nitc__model.sep.3.o nitc__mmodule.sep.1.o nitc__mpackage.sep.1.o nitc__model_base.sep.1.o nitc__location.sep.1.o core__ropes.sep.1.o core__flat.sep.1.o core__flat.sep.2.o core__abstract_text.sep.1.o core__native.sep.1.o core__kernel.sep.1.o core__math.sep.1.o core__abstract_collection.sep.1.o core__list.sep.1.o core__array.sep.1.o core__circular_array.sep.1.o core__sorter.sep.1.o core__hash_collection.sep.1.o core__fixed_ints.sep.1.o core__string_search.sep.1.o core__fixed_ints_text.sep.1.o core__environ.sep.1.o core__file.sep.1.o core__stream.sep.1.o core__error.sep.1.o core__bytes.sep.1.o core__utf8.sep.1.o core__time.sep.1.o core__exec.sep.1.o more_collections.sep.1.o poset.sep.1.o nitc__mdoc.sep.1.o ordered_tree.sep.1.o nitc__toolcontext.sep.1.o opts.sep.1.o nitc__version.sep.1.o template.sep.1.o nitc__parser.sep.1.o nitc__parser.sep.2.o nitc__parser.sep.3.o nitc__parser.sep.4.o nitc__parser.sep.5.o nitc__parser.sep.6.o nitc__parser.sep.7.o nitc__parser_prod.sep.1.o nitc__parser_prod.sep.2.o nitc__parser_prod.sep.3.o nitc__parser_prod.sep.4.o nitc__parser_prod.sep.5.o nitc__parser_prod.sep.6.o nitc__lexer.sep.1.o nitc__parser_nodes.sep.1.o nitc__lexer_work.sep.1.o nitc__tables.sep.1.o nitc__parser_work.sep.1.o ini.sep.1.o nitc__phase.sep.1.o nitc__annotation.sep.1.o nitc__literal.sep.1.o nitc__transform.sep.1.o nitc__astbuilder.sep.1.o nitc__typing.sep.1.o nitc__typing.sep.2.o nitc__typing.sep.3.o nitc__local_var_init.sep.1.o nitc__flow.sep.1.o nitc__scope.sep.1.o nitc__astvalidation.sep.1.o nitc__auto_super_init.sep.1.o nitc__rapid_type_analysis.sep.1.o csv.sep.1.o nitc__separate_erasure_compiler.sep.1.o nitc__separate_erasure_compiler.sep.2.o nitc__separate_compiler.sep.1.o nitc__separate_compiler.sep.2.o nitc__separate_compiler.sep.3.o nitc__separate_compiler.sep.4.o nitc__separate_compiler.sep.5.o nitc__separate_compiler.sep.6.o nitc__abstract_compiler.sep.1.o nitc__abstract_compiler.sep.2.o nitc__abstract_compiler.sep.3.o nitc__abstract_compiler.sep.4.o nitc__abstract_compiler.sep.5.o nitc__abstract_compiler.sep.6.o nitc__abstract_compiler.sep.7.o nitc__platform.sep.1.o nitc__c_tools.sep.1.o nitc__mixin.sep.1.o counter.sep.1.o nitc__coloring.sep.1.o nitc__light_only.sep.1.o nitc__light.sep.1.o nitc__light_ffi.sep.1.o nitc__nitni_utilities.sep.1.o nitc__nitni_base.sep.1.o nitc__light_ffi_base.sep.1.o nitc__extern_classes.sep.1.o nitc__light_c.sep.1.o nitc__nith.types.1.o nitc__nith.types.2.o nitc__nith.types.3.o nitc__nith.types.4.o nitc__nith.types.5.o nitc__nith.types.6.o nitc__nith.types.7.o nitc__nith.types.8.o nitc__nith.types.9.o nitc__nith.types.10.o nitc__nith.types.11.o nitc__nith.types.12.o nitc__nith.types.13.o nitc__nith.types.14.o nitc__nith.types.15.o nitc__nith.types.16.o nitc__nith.types.17.o nitc__nith.types.18.o nitc__nith.types.19.o nitc__nith.types.20.o nitc__nith.types.21.o nitc__nith.types.22.o nitc__nith.types.23.o nitc__nith.types.24.o nitc__nith.types.25.o nitc__nith.types.26.o nitc__nith.types.27.o nitc__nith.types.28.o nitc__nith.types.29.o nitc__nith.types.30.o nitc__nith.types.31.o nitc__nith.types.32.o nitc__nith.types.33.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o core__abstract_text._ffi.extern.o core__abstract_text._nitni.extern.o core__native._ffi.extern.o core__native._nitni.extern.o core__kernel._ffi.extern.o core__kernel._nitni.extern.o core__math._ffi.extern.o core__math._nitni.extern.o core__fixed_ints_text._ffi.extern.o core__fixed_ints_text._nitni.extern.o core__environ._ffi.extern.o core__environ._nitni.extern.o core__file._ffi.extern.o core__file._nitni.extern.o core__time._ffi.extern.o core__time._nitni.extern.o core__exec._ffi.extern.o core__exec._nitni.extern.o 2>/dev/null
+       rm -f nitc__nith.classes.1.o nitc__nith.classes.2.o nitc__nith.classes.3.o nitc__nith.classes.4.o nitc__nith.classes.5.o nitc__nith.classes.6.o nitc__nith.main.1.o nitc__nith.sep.1.o nitc__modelize_property.sep.1.o nitc__modelize_property.sep.2.o nitc__modelize_property.sep.3.o nitc__modelize_class.sep.1.o nitc__modelbuilder.sep.1.o nitc__loader.sep.1.o nitc__loader.sep.2.o nitc__modelbuilder_base.sep.1.o nitc__model.sep.1.o nitc__model.sep.2.o nitc__model.sep.3.o nitc__mmodule.sep.1.o nitc__mpackage.sep.1.o nitc__model_base.sep.1.o nitc__location.sep.1.o core__ropes.sep.1.o core__flat.sep.1.o core__flat.sep.2.o core__abstract_text.sep.1.o core__native.sep.1.o core__kernel.sep.1.o core__math.sep.1.o core__abstract_collection.sep.1.o core__list.sep.1.o core__array.sep.1.o core__circular_array.sep.1.o core__sorter.sep.1.o core__hash_collection.sep.1.o core__fixed_ints.sep.1.o core__string_search.sep.1.o core__fixed_ints_text.sep.1.o core__environ.sep.1.o core__file.sep.1.o core__stream.sep.1.o core__error.sep.1.o core__bytes.sep.1.o core__utf8.sep.1.o core__time.sep.1.o core__exec.sep.1.o more_collections.sep.1.o poset.sep.1.o nitc__mdoc.sep.1.o ordered_tree.sep.1.o nitc__toolcontext.sep.1.o opts.sep.1.o nitc__version.sep.1.o template.sep.1.o nitc__parser.sep.1.o nitc__parser.sep.2.o nitc__parser.sep.3.o nitc__parser.sep.4.o nitc__parser.sep.5.o nitc__parser.sep.6.o nitc__parser.sep.7.o nitc__parser_prod.sep.1.o nitc__parser_prod.sep.2.o nitc__parser_prod.sep.3.o nitc__parser_prod.sep.4.o nitc__parser_prod.sep.5.o nitc__parser_prod.sep.6.o nitc__lexer.sep.1.o nitc__parser_nodes.sep.1.o nitc__lexer_work.sep.1.o nitc__tables.sep.1.o nitc__parser_work.sep.1.o ini.sep.1.o nitc__phase.sep.1.o nitc__annotation.sep.1.o nitc__literal.sep.1.o nitc__transform.sep.1.o nitc__astbuilder.sep.1.o nitc__typing.sep.1.o nitc__typing.sep.2.o nitc__typing.sep.3.o nitc__local_var_init.sep.1.o nitc__flow.sep.1.o nitc__scope.sep.1.o nitc__astvalidation.sep.1.o nitc__auto_super_init.sep.1.o nitc__rapid_type_analysis.sep.1.o csv.sep.1.o nitc__separate_erasure_compiler.sep.1.o nitc__separate_erasure_compiler.sep.2.o nitc__separate_compiler.sep.1.o nitc__separate_compiler.sep.2.o nitc__separate_compiler.sep.3.o nitc__separate_compiler.sep.4.o nitc__separate_compiler.sep.5.o nitc__separate_compiler.sep.6.o nitc__abstract_compiler.sep.1.o nitc__abstract_compiler.sep.2.o nitc__abstract_compiler.sep.3.o nitc__abstract_compiler.sep.4.o nitc__abstract_compiler.sep.5.o nitc__abstract_compiler.sep.6.o nitc__abstract_compiler.sep.7.o nitc__platform.sep.1.o nitc__c_tools.sep.1.o nitc__mixin.sep.1.o counter.sep.1.o nitc__coloring.sep.1.o nitc__light_only.sep.1.o nitc__light.sep.1.o nitc__light_ffi.sep.1.o nitc__nitni_utilities.sep.1.o nitc__nitni_base.sep.1.o nitc__light_ffi_base.sep.1.o nitc__extern_classes.sep.1.o nitc__light_c.sep.1.o nitc__nith.types.1.o nitc__nith.types.2.o nitc__nith.types.3.o nitc__nith.types.4.o nitc__nith.types.5.o nitc__nith.types.6.o nitc__nith.types.7.o nitc__nith.types.8.o nitc__nith.types.9.o nitc__nith.types.10.o nitc__nith.types.11.o nitc__nith.types.12.o nitc__nith.types.13.o nitc__nith.types.14.o nitc__nith.types.15.o nitc__nith.types.16.o nitc__nith.types.17.o nitc__nith.types.18.o nitc__nith.types.19.o nitc__nith.types.20.o nitc__nith.types.21.o nitc__nith.types.22.o nitc__nith.types.23.o nitc__nith.types.24.o nitc__nith.types.25.o nitc__nith.types.26.o nitc__nith.types.27.o nitc__nith.types.28.o nitc__nith.types.29.o nitc__nith.types.30.o nitc__nith.types.31.o nitc__nith.types.32.o nitc__nith.types.33.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o core__abstract_text._ffi.extern.o core__abstract_text._nitni.extern.o core__native._ffi.extern.o core__native._nitni.extern.o core__kernel._ffi.extern.o core__kernel._nitni.extern.o core__math._ffi.extern.o core__math._nitni.extern.o core__fixed_ints_text._ffi.extern.o core__fixed_ints_text._nitni.extern.o core__environ._ffi.extern.o core__environ._nitni.extern.o core__file._ffi.extern.o core__file._nitni.extern.o core__time._ffi.extern.o core__time._nitni.extern.o core__exec._ffi.extern.o core__exec._nitni.extern.o 2>/dev/null
index 5c91a58..6eee80c 100644 (file)
@@ -12,7 +12,7 @@ It renders the earth with an displaced surface, a cloud layer, city lights and P
 
        This variation can show more models specified on the command line.
 
-       ~~~
+       ~~~raw
        bin/model_viewer [path_to_model ...]
        ~~~
 
index aa93fed..121633b 100644 (file)
@@ -14,21 +14,21 @@ Portable calculator built using _app.nit_
 
 * Compile and run on the desktop (GNU/Linux and OS X) with:
 
-       ~~~
+       ~~~raw
        make
        bin/calculator
        ~~~
 
 * Compile for Android and install on a device or emulator with:
 
-       ~~~
+       ~~~raw
        make bin/android.apk
        adb install -r bin/calculator.apk
        ~~~
 
 * Compile for iOS and run on the simulator with:
 
-       ~~~
+       ~~~raw
        make bin/android.app
        ios-sim launch bin/calculator.app
        ~~~
index 4baecf4..d69a030 100644 (file)
@@ -163,7 +163,7 @@ The _app.nit_ framework defines three annotations to customize the application p
 
 ## Usage Example
 
-~~~
+~~~nitish
 module my_module is
     app_name "My App"
     app_namespace "org.example.my_app"
@@ -183,7 +183,7 @@ There is two main ways to achieve this goal:
 * The mixin option (`-m module`) imports an additional module before compiling.
   It can be used to load platform specific implementations of the _app.nit_ portable UI.
 
-  ~~~
+  ~~~raw
   # GNU/Linux version, using GTK
   nitc calculator.nit -m linux
 
@@ -198,7 +198,7 @@ There is two main ways to achieve this goal:
   Continuing with the calculator example, it is adapted for Android by the module `android_calculator.nit`.
   This module imports both `calculator` and `android`, it can then use Android specific code.
 
-  ~~~
+  ~~~nitish
   module android_calculator
 
   import calculator
index 04dabfa..b51cd22 100644 (file)
@@ -396,6 +396,7 @@ interface SimpleCollection[E]
        fun add(item: E) is abstract
 
        # Add each item of `coll`.
+       #
        #     var a = [1,2]
        #     a.add_all([3..5])
        #     assert a.has(4)  == true
index 9419853..1cc757b 100644 (file)
@@ -19,11 +19,11 @@ import array
 
 # Efficient data structure to access both end of the sequence.
 #
-# A circular array offers efficient random access,
-# efficient manipulation for both ends of the structure (push, pop, ) and
+# A circular array offers efficient random access, efficient manipulation
+# at both ends of the structure (push, pop, shift and unshift) and
 # automatic amortized growth.
 #
-# Therefore it can be used as is or as and efficient queue (FIFO/LIFO)
+# Therefore it can be used as is or as an efficient queue (FIFO/LIFO).
 class CircularArray[E]
        super Sequence[E]
 
index b44b7f9..864c509 100644 (file)
@@ -13,7 +13,8 @@ module union_find
 
 import hash_collection
 
-# Data structure to keeps track of elements partitioned into disjoint subsets
+# Data structure to keep track of elements partitioned into disjoint subsets
+#
 #     var s = new DisjointSet[Int]
 #     s.add(1)
 #     s.add(2)
@@ -21,15 +22,15 @@ import hash_collection
 #     s.union(1,2)
 #     assert s.in_same_subset(1,2)
 #
-# `in_same_subset` is transitive, reflexive and symetric
+# `in_same_subset` is transitive, reflexive and symmetric
 #
 #     s.add(3)
 #     assert not s.in_same_subset(1,3)
 #     s.union(3,2)
 #     assert s.in_same_subset(1,3)
 #
-# Unkike theorical Disjoint-set data structures, the underling implementation is opaque
-# that makes the traditionnal `find` method unavailable for clients.
+# Unlike theoretical Disjoint-set data structures, the underling implementation is opaque
+# making the traditional `find` method unavailable for clients.
 # The methods `in_same_subset`, `to_partitions`, and their variations are offered instead.
 class DisjointSet[E]
        super SimpleCollection[E]
@@ -139,6 +140,7 @@ class DisjointSet[E]
        end
 
        # Are all elements of `es` in the same subset?
+       #
        #     var s = new DisjointSet[Int]
        #     s.add_all([1,2,3,4,5,6])
        #     s.union_all([1,2,3])
@@ -170,7 +172,7 @@ class DisjointSet[E]
                return to_subpartition(self)
        end
 
-       # Construct a partitionning on `es`, a subset of elements
+       # Construct a partitioning on `es`, a subset of elements
        #
        #     var s = new DisjointSet[Int]
        #     s.add_all([1,2,3,4,5,6])
@@ -235,7 +237,7 @@ private class DisjointSetNode
        # If parent == self then the node is a root
        var parent: DisjointSetNode = self
 
-       # The rank to no desequilibrate the structure.
+       # The rank to keep the structure balanced.
        # The term rank is used instead of depth since
        # path compression is used, see `DisjointSet::nfind`
        var rank = 0
index 45c3ccd..39a5958 100644 (file)
@@ -858,8 +858,11 @@ universal Int
 
        # Return the corresponding digit character
        # If 0 <= `self` <= 9, return the corresponding character.
+       #
        #     assert 5.to_c    == '5'
+       #
        # If 10 <= `self` <= 36, return the corresponding letter [a..z].
+       #
        #     assert 15.to_c   == 'f'
        fun to_c: Char
        do
index fbe045f..06989ef 100644 (file)
@@ -253,6 +253,7 @@ abstract class Text
        # assert "0x64".to_i       == 100
        # assert "0b1100_0011".to_i== 195
        # assert "--12".to_i       == 12
+       # assert "+45".to_i        == 45
        # ~~~
        #
        # REQUIRE: `self`.`is_int`
index c738f91..89f6553 100644 (file)
@@ -208,6 +208,8 @@ redef class Text
        #
        #     assert "123".is_int
        #     assert "0b1011".is_int
+       #     assert "-34".is_int
+       #     assert "+45".is_int
        #     assert not "0x_".is_int
        #     assert not "0xGE".is_int
        #     assert not "".is_int
@@ -218,7 +220,7 @@ redef class Text
                var s = remove_all('_')
                var pos = 0
                var len = s.length
-               while pos < len and s[pos] == '-' do
+               while pos < len and (s[pos] == '-' or s[pos] == '+') do
                        pos += 1
                end
                s = s.substring_from(pos)
@@ -238,9 +240,15 @@ redef class Text
                var val = 0
                var neg = false
                var pos = 0
-               while s[pos] == '-' do
-                       neg = not neg
-                       pos += 1
+               loop
+                       if s[pos] == '-' then
+                               neg = not neg
+                               pos += 1
+                       else if s[pos] == '+' then
+                               pos += 1
+                       else
+                               break
+                       end
                end
                s = s.substring_from(pos)
                if s.length >= 2 then
index 68370d9..7580370 100644 (file)
@@ -8,20 +8,20 @@ It is based on the portability framework _app.nit_ and the OpenGL ES 2.0 standar
 To compile the _gamnit_ apps packaged with the Nit repository on GNU/Linux you need to install the dev version of a few libraries and some tools.
 On Debian 8.2, this command should install everything needed:
 
-~~~
+~~~raw
 apt-get install libgles2-mesa-dev libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev inkscape
 ~~~
 
 On Windows 64 bits, using msys2, you can install the required packages with:
 
-~~~
+~~~raw
 pacman -S mingw-w64-x86_64-angleproject-git mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_image mingw-w64-x86_64-SDL2_mixer
 ~~~
 
 While macOS isn't supported, it can create iOS apps.
 You need to install and setup Xcode, and you may install the GLSL shader validation tool via `brew`:
 
-~~~
+~~~raw
 brew install glslang
 ~~~
 
index e518f8d..4eb9a97 100644 (file)
@@ -26,7 +26,7 @@ intrude import json::serialization_read
 #
 # To access the API you need an instance of a `GithubAPI` client.
 #
-# ~~~
+# ~~~nitish
 # # Get Github authentification token.
 # var token = get_github_oauth
 # assert not token.is_empty
@@ -37,7 +37,7 @@ intrude import json::serialization_read
 #
 # The API client allows you to get Github API entities.
 #
-# ~~~
+# ~~~nitish
 # var repo = api.load_repo("nitlang/nit")
 # assert repo != null
 # assert repo.name == "nit"
index ff10b05..ec7d290 100644 (file)
@@ -2,6 +2,7 @@
 #
 # Copyright 2013 Jean-Philippe Caissy <jpcaissy@piji.ca>
 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+# Copyright 2018 Matthieu Le Guellaut <leguellaut.matthieu@gmail.com>
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -38,6 +39,8 @@ in "C" `{
        #include <arpa/inet.h>
        #include <netinet/in.h>
        #include <netinet/ip.h>
+       #include <sys/un.h>
+       #include <unistd.h>
 
 // Protect callbacks for compatibility with light FFI
 #ifdef Connection_decr_ref
@@ -145,8 +148,6 @@ interface EventCallback
 end
 
 # Spawned to manage a specific connection
-#
-# TODO, use polls
 class Connection
        super Writer
 
@@ -418,31 +419,49 @@ end
 # A listener acting on an interface and port, spawns `Connection` on new connections
 extern class ConnectionListener `{ struct evconnlistener * `}
 
-       private new bind_to(base: NativeEventBase, address: CString, port: Int, factory: ConnectionFactory)
+       private new bind_tcp(base: NativeEventBase, address: CString, port: Int, factory: ConnectionFactory)
        import ConnectionFactory.accept_connection, error_callback `{
 
-               struct sockaddr_in sin;
-               struct evconnlistener *listener;
                ConnectionFactory_incr_ref(factory);
 
                struct hostent *hostent = gethostbyname(address);
-
                if (!hostent) {
                        return NULL;
                }
 
-               memset(&sin, 0, sizeof(sin));
+               struct sockaddr_in sin = {0};
                sin.sin_family = hostent->h_addrtype;
                sin.sin_port = htons(port);
                memcpy( &(sin.sin_addr.s_addr), (const void*)hostent->h_addr, hostent->h_length );
 
-               listener = evconnlistener_new_bind(base,
+               struct evconnlistener *listener = evconnlistener_new_bind(base,
                        (evconnlistener_cb)accept_connection_cb, factory,
                        LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
                        (struct sockaddr*)&sin, sizeof(sin));
+               if (listener != NULL) {
+                       evconnlistener_set_error_cb(listener,
+                               (evconnlistener_errorcb)ConnectionListener_error_callback);
+               }
+
+               return listener;
+       `}
+
+       private new bind_unix(base: NativeEventBase, file: CString, factory: ConnectionFactory)
+       import ConnectionFactory.accept_connection, error_callback `{
+
+               ConnectionFactory_incr_ref(factory);
+
+               struct sockaddr_un sun = {0};
+               sun.sun_family = AF_UNIX;
+               strncpy(sun.sun_path, file, sizeof(sun.sun_path) - 1);
 
+               struct evconnlistener *listener = evconnlistener_new_bind(base,
+                       (evconnlistener_cb)accept_connection_cb, factory,
+                       LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
+                       (struct sockaddr*)&sun, sizeof(sun));
                if (listener != NULL) {
-                       evconnlistener_set_error_cb(listener, (evconnlistener_errorcb)ConnectionListener_error_callback);
+                       evconnlistener_set_error_cb(listener,
+                               (evconnlistener_errorcb)ConnectionListener_error_callback);
                }
 
                return listener;
@@ -451,15 +470,17 @@ extern class ConnectionListener `{ struct evconnlistener * `}
        # Get the `NativeEventBase` associated to `self`
        fun base: NativeEventBase `{ return evconnlistener_get_base(self); `}
 
-       # Callback method on listening error
-       fun error_callback do
+       # Callback on listening error
+       fun error_callback
+       do
                var cstr = evutil_socket_error_to_string(evutil_socket_error)
-               print_error "libevent error: '{cstr}'"
+               print_error "libevent error: {cstr}"
        end
 end
 
 # Factory to listen on sockets and create new `Connection`
 class ConnectionFactory
+
        # The `NativeEventBase` for the dispatch loop of this factory
        var event_base: NativeEventBase
 
@@ -490,17 +511,45 @@ class ConnectionFactory
                return new Connection(buffer_event)
        end
 
-       # Listen on `address`:`port` for new connection, which will callback `spawn_connection`
-       fun bind_to(address: String, port: Int): nullable ConnectionListener
+       # Listen on the TCP socket at `address`:`port` for new connections
+       #
+       # On new connections, libevent callbacks `spawn_connection`.
+       fun bind_tcp(address: String, port: Int): nullable ConnectionListener
        do
-               var listener = new ConnectionListener.bind_to(event_base, address.to_cstring, port, self)
+               var listener = new ConnectionListener.bind_tcp(
+                       event_base, address.to_cstring, port, self)
+
                if listener.address_is_null then
-                       sys.stderr.write "libevent warning: Opening {address}:{port} failed\n"
+                       print_error "libevent warning: Opening {address}:{port} failed, " +
+                               evutil_socket_error_to_string(evutil_socket_error).to_s
+                       return null
                end
+
                return listener
        end
 
-       # Put string representation of source `address` into `buf`
+       # Listen on a UNIX domain socket for new connections
+       #
+       # On new connections, libevent callbacks `spawn_connection`.
+       fun bind_unix(path: String): nullable ConnectionListener
+       do
+               # Delete the socket if it already exists
+               var stat = path.file_stat
+               if stat != null and stat.is_sock then path.file_delete
+
+               var listener = new ConnectionListener.bind_unix(
+                       event_base, path.to_cstring, self)
+
+               if listener.address_is_null then
+                       print_error "libevent warning: Opening UNIX domain socket {path} failed, " +
+                               evutil_socket_error_to_string(evutil_socket_error).to_s
+                       return null
+               end
+
+               return listener
+       end
+
+       # Put a human readable string representation of `address` into `buf`
        private fun addrin_to_address(address: Pointer, buf: CString, buf_len: Int): CString `{
                struct sockaddr *addrin = (struct sockaddr*)address;
 
@@ -512,6 +561,14 @@ class ConnectionFactory
                        struct in6_addr *src = &((struct sockaddr_in6*)addrin)->sin6_addr;
                        return (char *)inet_ntop(addrin->sa_family, src, buf, buf_len);
                }
+               else if (addrin->sa_family == AF_UNIX) {
+                       struct sockaddr_un *src = (struct sockaddr_un*)addrin;
+                       char *path = src->sun_path;
+                       if (path == NULL) return "Unnamed UNIX domain socket";
+                       if (path[0] == '\0') return "Abstract UNIX domain socket";
+                       return path;
+               }
+
                return NULL;
        `}
 end
diff --git a/lib/libevent/libevent_example.nit b/lib/libevent/libevent_example.nit
new file mode 100644 (file)
index 0000000..c00917e
--- /dev/null
@@ -0,0 +1,57 @@
+# 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.
+
+# Minimal usage example of libevent
+module libevent_example is example
+
+import libevent
+
+# Factory creating instances of `EchoConnection` to handle new connections
+class MyFactory
+       super ConnectionFactory
+
+       redef fun spawn_connection(buf, address)
+       do
+               return new EchoConnection(buf)
+       end
+end
+
+# Connection echoing data received from clients back at them
+class EchoConnection
+       super Connection
+
+       redef fun read_callback(content)
+       do
+               print "Received: {content}"
+               write content
+       end
+end
+
+# Skip the actual execution when testing
+if "NIT_TESTING".environ == "true" then exit 0
+
+# Setup libevent system
+var event_base = new NativeEventBase
+var factory = new MyFactory(event_base)
+
+# Open a TCP socket for listening
+factory.bind_tcp("localhost", 8888)
+
+# Open a UNIX domain socket for listening
+factory.bind_unix("/tmp/my.sck")
+
+# Launch event loop
+event_base.dispatch
+
+event_base.free
diff --git a/lib/libevent/libevent_test.nit b/lib/libevent/libevent_test.nit
new file mode 100644 (file)
index 0000000..4c64b2e
--- /dev/null
@@ -0,0 +1,94 @@
+# 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 libevent_test
+
+import libevent
+import pthreads
+
+redef class Sys
+
+       var testing_id: Int is lazy do
+               var id = "NIT_TESTING_ID".environ
+               return if id.is_empty then 0 else id.to_i
+       end
+
+       # Config for test sockets
+       var tcp_addr = "localhost"
+       var tcp_port: Int = 20000 + testing_id
+       var unix_socket_path = "/tmp/libevent_test{testing_id}.sck"
+end
+
+class TestConnectionFactory
+       super ConnectionFactory
+
+       redef fun spawn_connection(buf, address)
+       do
+               print "[Server] New client: {address}"
+
+               var conn = new TestConnection(buf)
+               print "[Server] Write: Hi"
+               conn.write "Hi\n"
+               return conn
+       end
+end
+
+class TestConnection
+       super Connection
+
+       redef fun read_callback(content)
+       do
+               0.2.sleep # Forcing the server output after the client output
+               printn "[Server] Read: {content}"
+       end
+end
+
+class ServerThread
+       super Thread
+
+       redef fun main
+       do
+               var event_base = new NativeEventBase
+               var factory = new TestConnectionFactory(event_base)
+
+               # Bind TCP socket
+               factory.bind_tcp(tcp_addr, tcp_port)
+
+               # Bind UNIX domain socket
+               factory.bind_unix unix_socket_path
+
+               event_base.dispatch
+               event_base.free
+
+               return null
+       end
+end
+
+redef fun system(cmd)
+do
+       if testing_id == 0 then print "[Client] {cmd}"
+       return super(cmd)
+end
+
+# First, launch a server in the background
+var server = new ServerThread
+server.start
+0.1.sleep
+
+# Test what should succeed
+system "echo 'Hello TCP' | nc -N {tcp_addr} {tcp_port}"
+system "echo 'Hello UNIX' | nc -NU {unix_socket_path}"
+
+1.0.sleep
+exit 0
index c24d489..38f78e9 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name=libevent
-tags=wrapper,lib
+tags=network,wrapper,lib
 maintainer=Alexis Laferrière <alexis.laf@xymus.net>
 license=Apache-2.0
 desc=Low-level wrapper around the libevent library to manage events on file descriptors
index 85a2068..def3699 100644 (file)
@@ -176,7 +176,7 @@ redef class Sys
 
                var listener = listeners[name, port]
                if listener == null then
-                       listener = factory.bind_to(name, port)
+                       listener = factory.bind_tcp(name, port)
                        if listener != null then
                                sys.listeners[name, port] = listener
                                listeners_count[name, port] = 1
index d8ab3cb..585130e 100644 (file)
@@ -101,6 +101,7 @@ class Perfecthashing
        # n : number of required free identifiers
        # idc : This array will be filled with n free identifiers
        # return the size of hashTable to create for theses identifiers (mask + 1)
+       #
        #     var ph = new Perfecthashing
        #     var idc = new Array[Int]
        #     assert ph.pnand([3, 7, 10], 1, idc) == 6
index 2040c83..72003ec 100644 (file)
@@ -31,7 +31,7 @@
 # Repositories can be used in Popcorn app to manage your data persistence.
 # Here an example with a book management app:
 #
-# ~~~
+# ~~~nitish
 # # First we declare the `Book` class. It has to be serializable so it can be used
 # # within a `Repository`.
 #
@@ -252,7 +252,7 @@ end
 
 # A Repository that uses MongoDB as backend.
 #
-# ~~~
+# ~~~nitish
 # import popcorn
 # import popcorn::pop_repos
 # import popcorn::pop_json
index 3f6ac6c..3832465 100644 (file)
@@ -51,6 +51,8 @@ class Partnership
        redef fun ==(o) do return o isa SELF and partner_a == o.partner_a and partner_b == o.partner_b
        redef fun hash do return partner_a.hash + 1024*partner_b.hash
 end
+class Person
+end
 ~~~
 
 ### Scope of the `serialize` annotation
@@ -64,7 +66,7 @@ end
 * A module declaration annotated with `serialize` states that all its class definitions
   and locally declared attributes are serializable.
 
-  ~~~
+  ~~~nitish
   module shared_between_clients is serialize
   ~~~
 
@@ -155,7 +157,7 @@ For this customization, the following code snippet implements
 two serialization services: `User::core_serialize_to` and
 `Deserializer::deserialize_class`.
 
-~~~
+~~~nitish
 module user_credentials
 
 # User credentials for a website
@@ -233,7 +235,7 @@ you must use implementations of `Serializer` and `Deserializer`.
 The main implementations of these services are `JsonSerializer` and `JsonDeserializer`,
 from the `json_serialization` module.
 
-~~~
+~~~nitish
 import json
 import user_credentials
 
index 610ec2e..447a33f 100644 (file)
@@ -36,6 +36,7 @@ import abstract_tree
 #  * delete average O(lg n) worst O(n)
 #
 # Usage:
+#
 #     var tree = new BinTreeMap[Int, String]
 #     tree[1] = "n1"
 #     assert tree.min == "n1"
diff --git a/misc/docker/ci/Dockerfile b/misc/docker/ci/Dockerfile
new file mode 100644 (file)
index 0000000..0df6ea2
--- /dev/null
@@ -0,0 +1,82 @@
+# This is a basic install of Nit on a debian base.
+
+FROM debian:stretch
+MAINTAINER Jean Privat <jean@pryen.org>
+
+# Install dependencies
+RUN dpkg --add-architecture i386 \
+       && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+               # Recomanded builds pakages
+               build-essential \
+               ccache \
+               libgc-dev \
+               graphviz \
+               libunwind-dev \
+               pkg-config \
+               # Get the code!
+               git \
+               ca-certificates \
+               curl \
+               libcurl4-openssl-dev \
+               # For nit manpages :)
+               man \
+               # Get pip3 for junit2html
+               python3-dev \
+               python3-pip \
+               python3-setuptools \
+               python3-wheel \
+               # Packages needed for lib/
+               gettext \
+               libegl1-mesa-dev \
+               libevent-dev \
+               libgles1-mesa-dev \
+               libgles2-mesa-dev \
+               libgtk-3-dev \
+               libgmp-dev \
+               libmongoc-dev \
+               libbson-dev libssl-dev \
+               libncurses5-dev \
+               libpq-dev \
+               libreadline-dev \
+               libsdl-image1.2-dev \
+               libsdl-ttf2.0-dev \
+               libsdl1.2-dev \
+               libsdl2-dev \
+               libsdl2-image-dev \
+               libsdl2-mixer-dev \
+               libsqlite3-dev \
+               libx11-dev \
+               libxdg-basedir-dev \
+               postgresql \
+               # Packages needed for contrib, platforms and FFI
+               ant \
+               clang \
+               cmake \
+               default-jdk \
+               file \
+               gnupg \
+               gnuplot-nox \
+               inkscape \
+               libopenmpi-dev \
+               time \
+               unzip \
+               valgrind \
+               zipalign \
+               # Android
+               libc6:i386 \
+               libstdc++6:i386 \
+               zlib1g:i386 \
+               # TODO neo4j mongodb neo4j emscripten test_glsl_validation
+       && curl -sL https://deb.nodesource.com/setup_8.x | bash - \
+       && apt-get install -y nodejs \
+       && rm -rf /var/lib/apt/lists/*
+
+# Setup environment variables
+ENV JAVA_HOME=/usr/lib/jvm/default-java/
+ENV JNI_LIB_PATH=$JAVA_HOME/jre/lib/amd64/server/
+ENV LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64/server/
+
+RUN pip3 install junit2html
+
+#  Prepare to install npm (npm is not packaged for debian:stretch)
+RUN npm install pug-cli -g
diff --git a/misc/docker/ci/README.md b/misc/docker/ci/README.md
new file mode 100644 (file)
index 0000000..32e34a4
--- /dev/null
@@ -0,0 +1,6 @@
+# Docker image to run nit continuous integrations
+
+This image is used to run CI tests for nit.
+Because there is currently a lot of libraries and tools in Nit, a lot of Debian packages and other pieces of software are required.
+
+Note: this image does not contain Nit but is used as a base image to run full tests.
index 75e9cc5..32dd807 100644 (file)
@@ -556,9 +556,9 @@ endif
                end
                makefile.write("{outpath}: {dep_rules.join(" ")}\n\t$(CC) $(LDFLAGS) -o {outpath.escape_to_sh} {ofiles.join(" ")} $(LDLIBS) {pkg}\n\n")
                # Clean
-               makefile.write("clean:\n\trm {ofiles.join(" ")} 2>/dev/null\n")
+               makefile.write("clean:\n\trm -f {ofiles.join(" ")} 2>/dev/null\n")
                if outpath != real_outpath then
-                       makefile.write("\trm -- {outpath.escape_to_sh} 2>/dev/null\n")
+                       makefile.write("\trm -f -- {outpath.escape_to_sh} 2>/dev/null\n")
                end
                makefile.close
                self.toolcontext.info("Generated makefile: {makepath}", 2)
index a77a331..46f5a4a 100644 (file)
@@ -17,13 +17,12 @@ module testing_doc
 
 private import parser_util
 import testing_base
-import markdown
+import markdown2
 import html
 import realtime
 
 # Extractor, Executor and Reporter for the tests in a module
 class NitUnitExecutor
-       super HTMLDecorator
 
        # Toolcontext used to parse Nit code blocks.
        var toolcontext: ToolContext
@@ -40,12 +39,11 @@ class NitUnitExecutor
        # The name of the suite
        var name: String
 
-       # Markdown processor used to parse markdown comments and extract code.
-       var mdproc = new MarkdownProcessor
+       # Markdown parse used to parse markdown comments and extract code
+       private var md_parser = new MdParser
 
-       init do
-               mdproc.decorator = new NitunitDecorator(self)
-       end
+       # Markdown visitor used to extract markdown code blocks
+       private var md_visitor = new NitunitMdVisitor(self) is lazy
 
        # The associated documentation object
        var mdoc: nullable MDoc = null
@@ -58,8 +56,10 @@ class NitUnitExecutor
        # Is used because a new code-block might just be added to it.
        var last_docunit: nullable DocUnit = null
 
+       # Unit class name in XML output
        var xml_classname: String is noautoinit
 
+       # Unit name in xml output
        var xml_name: String is noautoinit
 
        # The entry point for a new `ndoc` node
@@ -73,17 +73,17 @@ class NitUnitExecutor
                self.mdoc = mdoc
 
                # Populate `blocks` from the markdown decorator
-               mdproc.process(mdoc.content.join("\n"))
+               var md_node = md_parser.parse(mdoc.content.join("\n"))
+               md_visitor.enter_visit(md_node)
        end
 
        # All extracted docunits
        var docunits = new Array[DocUnit]
 
-       fun show_status
-       do
-               toolcontext.show_unit_status(name, docunits)
-       end
+       # Display current testing status
+       fun show_status do toolcontext.show_unit_status(name, docunits)
 
+       # Update display when a test case is done
        fun mark_done(du: DocUnit)
        do
                du.is_done = true
@@ -274,6 +274,7 @@ class NitUnitExecutor
        # `file` should be a valid filepath for a Nit source file.
        private fun create_unitfile(file: String): Writer
        do
+               var mmodule = self.mmodule
                var dir = file.dirname
                if dir != "" then dir.mkdir
                var f
@@ -292,11 +293,12 @@ class NitUnitExecutor
        # Can terminate the program if the compiler is not found
        private fun compile_unitfile(file: String): Int
        do
+               var mmodule = self.mmodule
                var nitc = toolcontext.find_nitc
                var opts = new Array[String]
                if mmodule != null then
                        # FIXME playing this way with the include dir is not safe nor robust
-                       opts.add "-I {mmodule.filepath.dirname}"
+                       opts.add "-I {mmodule.filepath.as(not null).dirname}"
                end
                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)
@@ -343,17 +345,23 @@ class NitUnitExecutor
        end
 end
 
-private class NitunitDecorator
-       super HTMLDecorator
+private class NitunitMdVisitor
+       super MdVisitor
 
        var executor: NitUnitExecutor
 
-       redef fun add_code(v, block) do
-               var code = block.raw_content
-               var meta = block.meta or else "nit"
+       redef fun visit(node) do node.accept_nitunit(self)
+
+       fun parse_code(block: MdCodeBlock) do
+               var code = block.literal
+               if code == null then return
+
+               var meta = block.info or else "nit"
                # Do not try to test non-nit code.
                if meta != "nit" then return
+
                # Try to parse code blocks
+               var executor = self.executor
                var ast = executor.toolcontext.parse_something(code)
 
                var mdoc = executor.mdoc
@@ -364,12 +372,12 @@ private class NitunitDecorator
 
                # The location is computed according to the starts of the mdoc and the block
                # Note, the following assumes that all the comments of the mdoc are correctly aligned.
-               var loc = block.block.location
+               var loc = block.location
                var line_offset = loc.line_start + mdoc.location.line_start - 2
                var column_offset = loc.column_start + mdoc.location.column_start
                # Hack to handle precise location in blocks
                # TODO remove when markdown is more reliable
-               if block isa BlockFence then
+               if block isa MdFencedCodeBlock then
                        # Skip the starting fence
                        line_offset += 1
                else
@@ -423,8 +431,7 @@ private class NitunitDecorator
        end
 
        # Return and register a new empty docunit
-       fun new_docunit: DocUnit
-       do
+       fun new_docunit: DocUnit do
                var mdoc = executor.mdoc
                assert mdoc != null
 
@@ -442,6 +449,14 @@ private class NitunitDecorator
        end
 end
 
+redef class MdNode
+       private fun accept_nitunit(v: NitunitMdVisitor) do visit_all(v)
+end
+
+redef class MdCodeBlock
+       redef fun accept_nitunit(v) do v.parse_code(self)
+end
+
 # A unit-test extracted from some documentation.
 #
 # A docunit is extracted from the code-blocks of mdocs.
@@ -511,10 +526,13 @@ class DocUnit
        fun real_location(ast_location: Location): Location
        do
                var mdoc = self.mdoc
-               var res = new Location(mdoc.location.file, lines[ast_location.line_start-1],
+
+               var res = new Location(mdoc.location.file,
+                       lines[ast_location.line_start-1],
                        lines[ast_location.line_end-1],
                        columns[ast_location.line_start-1] + ast_location.column_start,
                        columns[ast_location.line_end-1] + ast_location.column_end)
+
                return res
        end
 
@@ -639,7 +657,7 @@ redef class ModelBuilder
        fun test_mdoc(mdoc: MDoc): HTMLTag
        do
                var ts = new HTMLTag("testsuite")
-               var file = mdoc.location.file.filename
+               var file = mdoc.location.file.as(not null).filename
 
                toolcontext.info("nitunit: doc-unit file {file}", 2)
 
index f733ce1..b3bb748 100644 (file)
@@ -17,9 +17,13 @@ import kernel
 class G[E]
        type V: nullable Object
 
-       fun foo
+       fun foo1
        do
                bar(1)
+       end
+
+       fun foo2
+       do
                baz(2)
        end
 
@@ -36,6 +40,9 @@ class I
        redef type V: Char
 end
 
-(new G[Object]).foo
-#alt1#(new H).foo
-#alt2#(new I).foo
+(new G[Object]).foo1
+(new G[Object]).foo2
+#alt1#(new H).foo1
+#alt1#(new H).foo2
+#alt2#(new I).foo1
+#alt2#(new I).foo2
diff --git a/tests/gitlab_ci.skip b/tests/gitlab_ci.skip
new file mode 100644 (file)
index 0000000..c611822
--- /dev/null
@@ -0,0 +1,13 @@
+android
+emscripten
+java
+glsl
+mongo
+mpi
+neo
+objc
+postgres
+action_nitro
+asteronits
+nitrpg
+wiringPi
index 8788ee7..8822457 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `V`, got `Int` (alt/base_autocast_alt2.nit:23)
+Runtime error: Cast failed. Expected `V`, got `Int` (alt/base_autocast_alt2.nit:27)
 1
 2
 1
index 46e2b1a..0a541aa 100644 (file)
@@ -7,7 +7,7 @@
 ../lib/core/kernel.nit:492,1--515,3: Error: `kernel$Bool` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
 ../lib/core/kernel.nit:517,1--599,3: Error: `kernel$Float` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
 ../lib/core/kernel.nit:601,1--700,3: Error: `kernel$Byte` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:702,1--883,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:885,1--1064,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:1066,1--1083,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:1085,1--1094,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:702,1--886,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:888,1--1067,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1069,1--1086,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1088,1--1097,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
diff --git a/tests/sav/gitlab_ci/simple_file_server.res b/tests/sav/gitlab_ci/simple_file_server.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/libevent_test.res b/tests/sav/libevent_test.res
new file mode 100644 (file)
index 0000000..b0f29bd
--- /dev/null
@@ -0,0 +1,8 @@
+[Server] New client: 127.0.0.1
+[Server] Write: Hi
+Hi
+[Server] Read: Hello TCP
+[Server] New client: Abstract UNIX domain socket
+[Server] Write: Hi
+Hi
+[Server] Read: Hello UNIX
index 1d1d69c..f1851ee 100644 (file)
@@ -1,17 +1,17 @@
 ==== Docunits of module test_nitunit::test_nitunit | tests: 5
 [OK] test_nitunit::test_nitunit
 [KO] test_nitunit$X
-     test_nitunit.nit:21,7--22,0: Runtime error in nitunit.out/test_nitunit-2.nit with argument 0
+     test_nitunit.nit:23,7--24,0: Runtime error in nitunit.out/test_nitunit-2.nit with argument 0
      Output
        Runtime error: Assert failed (nitunit.out/test_nitunit-2.nit:5)
 
 [KO] test_nitunit$X$foo
-     test_nitunit.nit:24,8--25,0: Compilation error in nitunit.out/test_nitunit-3.nit
+     test_nitunit.nit:27,8--28,0: Compilation error in nitunit.out/test_nitunit-3.nit
      Output
        nitunit.out/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
 
 [KO] test_nitunit$X$foo1
-     test_nitunit.nit:28,15: Syntax Error: unexpected operator '!'.
+     test_nitunit.nit:32,15: Syntax Error: unexpected operator '!'.
 [OK] test_nitunit$X$foo2
 
 ==== Test-suite of module test_test_nitunit::test_test_nitunit | tests: 3
index 30f2862..afcfb13 100644 (file)
@@ -5,7 +5,7 @@
        Runtime error: Assert failed (nitunit.out/test_nitunit3-0.nit:7)
 
 [KO] test_nitunit3>#2
-     test_nitunit3/README.md:7,3--5: Syntax Error: unexpected malformed character '\].
+     test_nitunit3/README.md:8,3--5: Syntax Error: unexpected malformed character '\].
 
 ==== Docunits of module test_nitunit3::test_nitunit3 | tests: 1
 [OK] test_nitunit3::test_nitunit3
index 12d09fe..4d7cf99 100644 (file)
@@ -1 +1 @@
-libevent warning: Opening localhost:80 failed
+libevent warning: Opening localhost:80 failed, Permission denied
index e3b3301..64bc744 100644 (file)
 # limitations under the License.
 
 # a 'success' unit test (pass)
+#
 #     assert true
 module test_nitunit
 # a 'error' unit test (do not pass)
+#
 #     assert false
 class X
        # a 'failure' unit test (does not compile)
+       #
        #     assert undefined_identifier
        fun foo do end
 
        # a 'failure' unit test (does not parse)
+       #
        #     assert !@#$%^&*()
        fun foo1(a, b: Int) do end
 
index 9eda24c..b771914 100755 (executable)
@@ -407,6 +407,11 @@ need_skip()
                echo >>$xml "<testcase classname='`xmlesc "$3"`' name='`xmlesc "$2"`' `timestamp`><skipped/></testcase>"
                return 0
        fi
+       if test -n "GITLAB_CI" && echo "$1" | grep -f "gitlab_ci.skip" >/dev/null 2>&1; then
+               echo "=> $2: [skip gitlab ci]"
+               echo >>$xml "<testcase classname='`xmlesc "$3"`' name='`xmlesc "$2"`' `timestamp`><skipped/></testcase>"
+               return 0
+       fi
 
        # Skip by OS
        local os_skip_file=$UNAME.skip
@@ -572,6 +577,7 @@ case $engine in
 esac
 
 savdirs="sav/`$HOSTNAME` sav/$UNAME sav/$engine $savdirs sav/"
+test -n "$GITLAB_CI" && savdirs="sav/gitlab_ci $savdirs"
 
 # The default nitc compiler
 [ -z "$NITC" ] && find_nitc