ounit-2.0.0/ 0000755 0001750 0001750 00000000000 12222142072 012163 5 ustar gildor gildor ounit-2.0.0/README.txt 0000644 0001750 0001750 00000001076 12222142072 013665 0 ustar gildor gildor (* OASIS_START *) (* DO NOT EDIT (digest: ac260da3dc5dbc8b63343daec02e41ac) *) This is the README file for the ounit distribution. (C) 2002-2008 Maas-Maarten Zeeman (C) 2010 OCamlCore SARL Unit testing framework OUnit is a unit testing framework for OCaml, inspired by the JUnit tool for Java, and the HUnit tool for Haskell. More information on [HUnit](http://hunit.sourceforge.net) See the files INSTALL.txt for building and installation instructions. See the file LICENSE.txt for copying conditions. Home page: http://ounit.forge.ocamlcore.org (* OASIS_STOP *) ounit-2.0.0/INSTALL.txt 0000644 0001750 0001750 00000001616 12222142072 014036 0 ustar gildor gildor (* OASIS_START *) (* DO NOT EDIT (digest: 6437cd9729746ca802a297a2cbec36cf) *) This is the INSTALL file for the ounit distribution. This package uses OASIS to generate its build system. See section OASIS for full information. Dependencies ============ In order to compile this package, you will need: * ocaml (>= 3.11.0) for all, test main, doc api-ounit * findlib * xmllint for test main Installing ========== 1. Uncompress the source archive and go to the root of the package 2. Run 'ocaml setup.ml -configure' 3. Run 'ocaml setup.ml -build' 4. Run 'ocaml setup.ml -install' Uninstalling ============ 1. Go to the root of the package 2. Run 'ocaml setup.ml -uninstall' OASIS ===== OASIS is a program that generates a setup.ml file using a simple '_oasis' configuration file. The generated setup only depends on the standard OCaml installation: no additional library is required. (* OASIS_STOP *) ounit-2.0.0/AUTHORS.txt 0000644 0001750 0001750 00000000225 12222142072 014050 0 ustar gildor gildor (* OASIS_START *) (* DO NOT EDIT (digest: 2915822545ee2a6c6708508e9418550d) *) Authors of ounit Maas-Maarten Zeeman Sylvain Le Gall (* OASIS_STOP *) ounit-2.0.0/doc/ 0000755 0001750 0001750 00000000000 12222142072 012730 5 ustar gildor gildor ounit-2.0.0/doc/manual.txt 0000644 0001750 0001750 00000020433 12222142072 014750 0 ustar gildor gildor {!indexlist} {2 What is unit Testing?} A test-oriented methodology for software development is most effective whent tests are easy to create, change, and execute. The JUnit tool pioneerded for test-first development in Java. OUnit is an adaptation of JUnit to OCaml. With OUnit, as with JUnit, you can easily create tests, name them, group them into suites, and execute them, with the framework checking the results automatically. {2 Getting Started} The basic principle of a test suite is to have a file {i test.ml} which will contain the tests, and an OCaml module under test, named {i foo.ml}. File {i foo.ml}: {[ (* The functions we wish to test *) let unity x = x;; let funix ()= 0;; let fgeneric () = failwith "Not implemented";; ]} The main point of a test is to check that the function under test has the expected behavior. You check the behavior using assert functions. The most simple one is {!OUnit2.assert_equal}. This function compares the result of the function with an expected result. The most useful functions are: - {!OUnit2.assert_equal} the basic assert function - {!OUnit2.(>:::)} to define a list of tests - {!OUnit2.(>::)} to name a test - {!OUnit2.run_test_tt_main} to run the test suite you define - {!OUnit2.bracket_tmpfile} that create a temporary filename. - {!OUnit2.bracket_tmpdir} that create a temporary directory. File {i test.ml}: {[ open OUnit2;; let test1 test_ctxt = assert_equal "x" (Foo.unity "x");; let test2 test_ctxt = assert_equal 100 (Foo.unity 100);; (* Name the test cases and group them together *) let suite = "suite">::: ["test1">:: test1; "test2">:: test2] ;; let () = run_test_tt_main suite ;; ]} And compile the module {[ $ ocamlfind ocamlc -o test -package oUnit -linkpkg -g foo.ml test.ml ]} A executable named "test" will be created. When run it produces the following output. {[ $ ./tests .. Ran: 2 tests in: 0.00 Seconds OK ]} When using {!OUnit2.run_test_tt_main}, a non zero exit code signals that the test suite was not successful. {2 Advanced usage} The topics, cover here, are only for advanced users who wish to unravel the power of OUnit. {!modules: OUnit2} {3 Error reporting} The error reporting part of OUnit is quite important. If you want to identify the failure, you should tune the display of the value and the test. Here is a list of thing you can display: - name of the test: OUnit use numbers to define path's test. But an error reporting about a failed test "0:1:2" is less explicit than "OUnit:0:comparator:1:float_comparator:2" - [~msg] parameter: it allows you to define say which assert has failed in your test. When you have more than one assert in a test, you should provide a [~msg] to be able to make the difference - [~printer] parameter: {!OUnit2.assert_equal} allows you to define a printer for compared values. A message ["abcd" is not equal to "defg"] is better than [not equal] {[ open OUnit2;; let _ = "mytest">:: (fun test_ctxt -> assert_equal ~msg:"int value" ~printer:string_of_int 1 (Foo.unity 1)) ;; ]} {3 Command line arguments} {!OUnit2.run_test_tt_main} already provides a set of command line argument to help user to run only the test he wants: - [-only-test]: skip all the tests except this one, you can use this flag several time to select more than one test to run - [-list-test]: list all the available tests and exit - [-help]: display help message and exit It is also possible to add your own command-line arguments, environment variable and config file variable. You should do it if you want to define some extra arguments. For example: {[ open OUnit2;; let my_program = Conf.make_exec "my_program" ;; let test1 test_ctxt = assert_command (my_program test_ctxt) [] ;; let () = run_test_tt_main ("test1" >:: test1) ;; ]} The [Conf.make_*] creates a command line argument, an environment variable and a config file variable. {3 Skip and todo tests} Tests are not always meaningful and can even fail because something is missing in the environment. In order to manage this, you can define a skip condition that will skip the test. If you start by defining your tests rather than implementing the functions under test, you know that some tests will just fail. You can mark these tests as to do tests, this way they will be reported differently in your test suite. {[ open OUnit2;; let _ = "allfuns" >::: [ "funix">:: (fun test_ctxt -> skip_if (Sys.os_type = "Win32") "Don't work on Windows"; assert_equal 0 (Foo.funix ())); "fgeneric">:: (fun test_ctxt -> todo "fgeneric not implemented"; assert_equal 0 (Foo.fgeneric ())); ] ;; ]} {3 Effective OUnit} This section is about general tips about unit testing and OUnit. It is the result of some years using OUnit in real world applications. - test everything: the more you create tests, the better chance you have to catch early an error in your program. Every submitted bugs to your application should have a matching tests. This is a good practice, but it is not always easy to implement. - test only what is really exported: on the long term, you have to maintain your test suite. If you test low-level functions, you'll have a lot of tests to rewrite. You should focus on creating tests for functions for which the behavior shouldn't change. - test fast: the best test suite is the one that runs after every single build. You should set your default Makefile target to run the test suite. It means that your test suite should be fast to run, typically, a 10s test suite is fine. - test long: contrary to the former tip, you should also have a complete test suite which can be very long to run. The best way to achieve both tips, is to define a command line arguments [-long] and skip the tests that are too long in your test suite according to it. When you do a release, you should use run your long test suite. - family tests: when testing behavior, most of the time you call exactly the same code with different arguments. In this case [List.map] and {!OUnit2.(>:::)} are your friends. For example: {[ open OUnit2;; let _ = "Family">::: (List.map (fun (arg,res) -> let title = Printf.sprintf "%s->%s" arg res in title >:: (fun test_ctxt -> assert_equal res (Foo.unity arg))) ["abcd", "abcd"; "defg", "defg"; "wxyz", "wxyz"]) ;; ]} - test failures and successes: the most obvious thing you want to test are successes, i.e. that you get the expected behavior in the normal case. But most of the errors arise in corner cases and in the code of the test itself. For example, you can have a partial application of your {!OUnit2.assert_equal} and never encounter any errors, just because the [assert_equal] is not called. In this case, if you test errors as well, you will have a missing errors as well. - set up and clean your environment in the test: you should not set up and clean your test environment outside the test. Ideally, if you run no tests, the program should do nothing. This is also a sane way to be sure that you are always testing in a clean environment, not polluted by the result of failed tests run before. This include the process environment, like current working directory. {[ open OUnit2;; let _ = (* We need to call a function in a particular directory *) "change-dir-and-run">:: (fun test_ctxt -> assert_command ~chdir:"/foo/test" "ls" []) ;; ]} - separate your test: OUnit test code should live outside the code under a directory called {i test}. This allow to drop the dependency on OUnit when distributing your library/application. This also enables people to easily make a difference from what really matters (the main code) and what are only tests. It is possible to have it directly in the code, like in Quickcheck style tests. The unit testing scope is always hard to define. Unit testing should be about testing a single features. But OUnit can help you to test higher level behavior, by running a full program for example. While it isn't real unit testing, you can use OUnit to do it and should not hesitate to do it. In term of line of codes, a test suite can represent from 10% to 150% of the code under test. With time, your test suite will grow faster than your program/library. A good ratio is 33%. @author Maas-Maarten Zeeman @author Sylvain Le Gall ounit-2.0.0/examples/ 0000755 0001750 0001750 00000000000 12222142072 014001 5 ustar gildor gildor ounit-2.0.0/examples/Makefile 0000644 0001750 0001750 00000005327 12222142072 015450 0 ustar gildor gildor ############################################################################ # The OUnit library # # # # Copyright (C) 2002-2008 Maas-Maarten Zeeman. # # Copyright (C) 2010 OCamlCore SARL # # Copyright (C) 2013 Sylvain Le Gall # # # # The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL # # and Sylvain Le Gall. # # # # Permission is hereby granted, free of charge, to any person obtaining # # a copy of this document and the OUnit software ("the Software"), to # # deal in the Software without restriction, including without limitation # # the rights to use, copy, modify, merge, publish, distribute, # # sublicense, and/or sell copies of the Software, and to permit persons # # to whom the Software is furnished to do so, subject to the following # # conditions: # # # # The above copyright notice and this permission notice shall be # # included in all copies or substantial portions of the Software. # # # # The Software is provided ``as is'', without warranty of any kind, # # express or implied, including but not limited to the warranties of # # merchantability, fitness for a particular purpose and noninfringement. # # In no event shall Maas-Maarten Zeeman be liable for any claim, damages # # or other liability, whether in an action of contract, tort or # # otherwise, arising from, out of or in connection with the Software or # # the use or other dealings in the software. # # # # See LICENSE.txt for details. # ############################################################################ TESTS = test_list.ml test_list2.ml test_stack.ml test: test_suite example -./test_suite -./example test_suite: $(TESTS) test_suite.ml ocamlfind ocamlc -o test_suite -package oUnit -linkpkg \ test_list.ml test_list2.ml test_stack.ml test_suite.ml example: example.ml ocamlfind ocamlc -o example -package oUnit -linkpkg \ example.ml clean: -$(RM) *.cmi *.cmo test_suite example ounit-2.0.0/examples/example.ml 0000644 0001750 0001750 00000005447 12222142072 016000 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnit let empty_list = [] let list_a = [1;2;3] let test_list_length _ = assert_equal 1 (List.length empty_list); assert_equal 3 (List.length list_a) (* etc, etc *) let test_list_append _ = let list_b = List.append empty_list [1;2;3] in assert_equal list_b list_a let suite = "OUnit Example" >::: ["test_list_length" >:: test_list_length; "test_list_append" >:: test_list_append] let _ = run_test_tt_main suite ounit-2.0.0/examples/test_list.ml 0000644 0001750 0001750 00000005451 12222142072 016352 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnit let empty_list = [] let list_a = [1;2;3] let test_list_length _ = assert_equal 1 (List.length empty_list); assert_equal 3 (List.length list_a) (* etc, etc *) let test_list_append _ = let list_b = List.append empty_list [1;2;3] in assert_equal list_b list_a let suite = "OUnit Example" >::: ["test_list_length" >:: test_list_length; "test_list_append" >:: test_list_append] let () = run_test_tt_main suite ounit-2.0.0/examples/test_list2.ml 0000644 0001750 0001750 00000005403 12222142072 016431 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnit let empty_list = [] let list_a = [1;2;3] let test_list_length _ = assert_equal 1 (List.length empty_list); assert_equal 3 (List.length list_a) (* etc, etc *) let test_list_append _ = let list_b = List.append empty_list [1;2;3] in assert_equal list_b list_a let suite = "Test_list2" >::: ["test_list_length2" >:: test_list_length; "test_list_append2" >:: test_list_append] ounit-2.0.0/examples/test_stack.ml 0000644 0001750 0001750 00000006240 12222142072 016501 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnit (* * This test shows how brackets can be used. They are handy to create * a so called fixture, which can be used for multiple tests *) (* prepare a stack for test *) let setup _ = let s = Stack.create () in Stack.push 1 s; Stack.push 2 s; Stack.push 3 s; s let teardown _ = () let test_top stack = assert_equal 3 (Stack.top stack) let test_clear stack = Stack.clear stack; assert_raises Stack.Empty (fun _ -> Stack.top stack) let test_pop stack = assert_equal 3 (Stack.pop stack); assert_equal 2 (Stack.pop stack); assert_equal 1 (Stack.pop stack); assert_raises Stack.Empty (fun _ -> Stack.pop stack) let suite = "Test Stack" >::: ["test_top" >:: (bracket setup test_top teardown); "test_clear" >:: (bracket setup test_clear teardown); "test_pop" >:: (bracket setup test_pop teardown)] ounit-2.0.0/examples/test_suite.ml 0000644 0001750 0001750 00000005042 12222142072 016524 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnit (* Collect the tests of different modules into one test suite *) let suite = "OUnit Example" >::: [Test_list.suite; Test_list2.suite; Test_stack.suite] let _ = run_test_tt_main suite ounit-2.0.0/src/ 0000755 0001750 0001750 00000000000 12222142072 012752 5 ustar gildor gildor ounit-2.0.0/src/oUnitThreads.mllib 0000644 0001750 0001750 00000000164 12222142072 016405 0 ustar gildor gildor # OASIS_START # DO NOT EDIT (digest: c233265d9f83eaa73923c9bdefb32777) OUnitThreads OUnitRunnerThreads # OASIS_STOP ounit-2.0.0/src/oUnitAdvanced.mllib 0000644 0001750 0001750 00000000611 12222142072 016515 0 ustar gildor gildor # OASIS_START # DO NOT EDIT (digest: 63cc39f68c681144d83ffd81399dc187) OUnitUtils OUnitPropList OUnitPlugin OUnitChooser OUnitResultSummary OUnitLoggerStd OUnitLoggerHTML OUnitLoggerHTMLData OUnitLoggerJUnit OUnitAssert OUnitBracket OUnitTest OUnitState OUnitRunner OUnitRunnerProcesses OUnitCore OUnitLogger OUnitConf OUnitShared OUnitCache OUnitTestData OUnitCheckEnv OUnitDiff # OASIS_STOP ounit-2.0.0/src/oUnit.mllib 0000644 0001750 0001750 00000000141 12222142072 015065 0 ustar gildor gildor # OASIS_START # DO NOT EDIT (digest: 1ad80d12b97eab491c61097067896fca) OUnit OUnit2 # OASIS_STOP ounit-2.0.0/src/api-ounit.odocl 0000644 0001750 0001750 00000000643 12222142072 015704 0 ustar gildor gildor # OASIS_START # DO NOT EDIT (digest: 1852896df1df5ea91216b5992e35cb92) OUnit OUnit2 OUnitThreads OUnitUtils OUnitPropList OUnitPlugin OUnitChooser OUnitResultSummary OUnitLoggerStd OUnitLoggerHTML OUnitLoggerHTMLData OUnitLoggerJUnit OUnitAssert OUnitBracket OUnitTest OUnitState OUnitRunner OUnitRunnerProcesses OUnitCore OUnitLogger OUnitConf OUnitShared OUnitCache OUnitTestData OUnitCheckEnv OUnitDiff # OASIS_STOP ounit-2.0.0/src/META 0000644 0001750 0001750 00000001636 12222142072 013431 0 ustar gildor gildor # OASIS_START # DO NOT EDIT (digest: ec034dc2b5280f95f8153b873aff4953) version = "2.0.0" description = "Unit testing framework" requires = "unix oUnit.advanced" archive(byte) = "oUnit.cma" archive(byte, plugin) = "oUnit.cma" archive(native) = "oUnit.cmxa" archive(native, plugin) = "oUnit.cmxs" exists_if = "oUnit.cma" package "threads" ( version = "2.0.0" description = "Unit testing framework" requires = "threads oUnit" archive(byte) = "oUnitThreads.cma" archive(byte, plugin) = "oUnitThreads.cma" archive(native) = "oUnitThreads.cmxa" archive(native, plugin) = "oUnitThreads.cmxs" exists_if = "oUnitThreads.cma" ) package "advanced" ( version = "2.0.0" description = "Unit testing framework" archive(byte) = "oUnitAdvanced.cma" archive(byte, plugin) = "oUnitAdvanced.cma" archive(native) = "oUnitAdvanced.cmxa" archive(native, plugin) = "oUnitAdvanced.cmxs" exists_if = "oUnitAdvanced.cma" ) # OASIS_STOP ounit-2.0.0/src/oUnit.css 0000644 0001750 0001750 00000007755 12222142072 014600 0 ustar gildor gildor /**************************************************************************/ /* The OUnit library */ /* */ /* Copyright (C) 2002-2008 Maas-Maarten Zeeman. */ /* Copyright (C) 2010 OCamlCore SARL */ /* Copyright (C) 2013 Sylvain Le Gall */ /* */ /* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL */ /* and Sylvain Le Gall. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this document and the OUnit software ("the Software"), to */ /* deal in the Software without restriction, including without limitation */ /* the rights to use, copy, modify, merge, publish, distribute, */ /* sublicense, and/or sell copies of the Software, and to permit persons */ /* to whom the Software is furnished to do so, subject to the following */ /* conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* The Software is provided ``as is'', without warranty of any kind, */ /* express or implied, including but not limited to the warranties of */ /* merchantability, fitness for a particular purpose and noninfringement. */ /* In no event shall Maas-Maarten Zeeman be liable for any claim, damages */ /* or other liability, whether in an action of contract, tort or */ /* otherwise, arising from, out of or in connection with the Software or */ /* the use or other dealings in the software. */ /* */ /* See LICENSE.txt for details. */ /**************************************************************************/ h1 { font-size: 26px; margin-right: 15px; padding-left: 0px; } h2 { font-size: 20px; margin-right: 15px; padding-left: 5px; } #ounit-current h2 { text-decoration: underline; } #ounit-results-started-at { width: 100%; } .ounit-results-content div { width: 150px; margin-top: 1px; } .ounit-results-content .number { text-align: right; display: inline-block; float: right; width: 50px; } .ounit-results-verdict.ounit-failure { color: red; } .ounit-success h2, .ounit-results-successes .number { background-color: #4a4; } .ounit-failure h2, .ounit-results-failures .number { background-color: #f66; } .ounit-error h2, .ounit-results-errors .number { background-color: #000; color: #fff; } .ounit-skip h2, .ounit-results-skips .number { background-color: #fd0; } .ounit-todo h2, .ounit-results-todos .number { background-color: #aaf; } .ounit-timeout h2, .ounit-results-timeouts .number { background-color: #888; } .ounit-conf h2, .ounit-results h2 { background-color: #aaa; } .ounit-log, .ounit-conf-content { font-family: Lucida Console, Monaco, Courier New, monospace; white-space: nowrap; font-size: 16px; color: #666; margin-left: 20px; } .ounit-duration, .ounit-started-at, .ounit-results-content { margin-bottom: 10px; margin-left: 15px; } .ounit-started-at { margin-bottom: 0; } span.ounit-timestamp { display: inline-block; width: 70px; } .ounit-log .ounit-result, .ounit-results-verdict { font-weight: bold; margin-top: 5px; } #navigation { position: fixed; top: 0; right: 0; background-color: #fff; padding: 9px; border: 1px solid #000; border-top: none; border-right: none; }; ounit-2.0.0/src/oUnit.js 0000644 0001750 0001750 00000007403 12222142072 014412 0 ustar gildor gildor /**************************************************************************/ /* The OUnit library */ /* */ /* Copyright (C) 2002-2008 Maas-Maarten Zeeman. */ /* Copyright (C) 2010 OCamlCore SARL */ /* Copyright (C) 2013 Sylvain Le Gall */ /* */ /* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL */ /* and Sylvain Le Gall. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this document and the OUnit software ("the Software"), to */ /* deal in the Software without restriction, including without limitation */ /* the rights to use, copy, modify, merge, publish, distribute, */ /* sublicense, and/or sell copies of the Software, and to permit persons */ /* to whom the Software is furnished to do so, subject to the following */ /* conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* The Software is provided ``as is'', without warranty of any kind, */ /* express or implied, including but not limited to the warranties of */ /* merchantability, fitness for a particular purpose and noninfringement. */ /* In no event shall Maas-Maarten Zeeman be liable for any claim, damages */ /* or other liability, whether in an action of contract, tort or */ /* otherwise, arising from, out of or in connection with the Software or */ /* the use or other dealings in the software. */ /* */ /* See LICENSE.txt for details. */ /**************************************************************************/ var successHidden = true; function displaySuccess(display) { var div = document.getElementsByClassName('ounit-success'); for (var i = 0; i < div.length; i++) { div[i].style.display = display; }; }; function toggleSuccess() { if (successHidden) { displaySuccess('block'); } else { displaySuccess('none'); }; successHidden = ! successHidden; var button = document.getElementById('toggleVisibiltySuccess'); if (successHidden) { button.textContent = 'Show success'; } else { button.textContent = 'Hide success'; }; }; function resetTestCurrent() { var div = document.getElementById('ounit-current'); if (div) { div.removeAttribute('id'); }; }; function setTestCurrent(div) { resetTestCurrent(); div.id = "ounit-current"; div.scrollIntoView(true); }; function nextTest() { var div = document.getElementsByClassName('ounit-test'); var found = false; var foundCurrent = false; var idx = 0; if (div) { for (; !found && idx < div.length; idx++) { if (foundCurrent && div[idx].style.display != 'none') { found = true; }; if (div[idx].id == "ounit-current") { foundCurrent = true; }; }; if (!foundCurrent && div.length > 0) { setTestCurrent(div[0]); } else if (found) { setTestCurrent(div[idx - 1]); } else { resetTestCurrent(); }; }; }; function gotoTop() { window.scrollTo(0,0); resetTestCurrent(); }; ounit-2.0.0/src/oUnit.ml 0000644 0001750 0001750 00000026536 12222142072 014416 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnitUtils let get_test_context, set_test_context, reset_test_context = let context_opt = ref None in (* get *) (fun () -> match !context_opt with | Some ctxt -> ctxt | None -> failwith "Function need to be called from inside a test."), (fun ctxt -> context_opt := Some ctxt), (fun ctxt -> context_opt := None) type node = ListItem of int | Label of string let node1_of_node = function | OUnitTest.ListItem i -> ListItem i | OUnitTest.Label s -> Label s let node_of_node1 = function | ListItem i -> OUnitTest.ListItem i | Label s -> OUnitTest.Label s type path = node list let path1_of_path pth = List.map node1_of_node pth type test_fun = unit -> unit type test = TestCase of test_fun | TestList of test list | TestLabel of string * test let rec test1_of_test = function | OUnitTest.TestCase (_, f) -> TestCase (fun () -> f (get_test_context ())) | OUnitTest.TestList lst -> TestList (List.map test1_of_test lst) | OUnitTest.TestLabel (str, tst) -> TestLabel (str, test1_of_test tst) let rec test_of_test1 = function | TestCase f -> OUnitTest.TestCase (OUnitTest.Short, fun ctxt -> set_test_context ctxt; f (); reset_test_context ()) | TestList lst -> OUnitTest.TestList (List.map test_of_test1 lst) | TestLabel (str, tst) -> OUnitTest.TestLabel (str, test_of_test1 tst) let rec ounit2_of_ounit1 = function | TestCase f -> OUnit2.test_case (fun ctxt -> set_test_context ctxt; f (); reset_test_context ()) | TestList lst -> OUnit2.test_list (List.map ounit2_of_ounit1 lst) | TestLabel (lbl, test) -> OUnit2.( >: ) lbl (ounit2_of_ounit1 test) type test_result = RSuccess of path | RFailure of path * string | RError of path * string | RSkip of path * string | RTodo of path * string let test_result1_of_test_result path rslt = let path1 = path1_of_path path in let rslt1 = match rslt with | OUnitTest.RSuccess -> RSuccess path1 | OUnitTest.RFailure (str, _, _) -> RFailure (path1, str) | OUnitTest.RError (str, _) -> RError (path1, str) | OUnitTest.RSkip str -> RSkip (path1, str) | OUnitTest.RTodo str -> RTodo (path1, str) | OUnitTest.RTimeout test_length -> RError (path1, (Printf.sprintf "timeout after %.1fs." (OUnitTest.delay_of_length test_length))) in rslt1 type test_event = EStart of path | EEnd of path | EResult of test_result let result_path = function | RSuccess path | RError (path, _) | RFailure (path, _) | RSkip (path, _) | RTodo (path, _) -> path type test_results = test_result list let list_result1_of_list_result = List.map (fun (pth, rslt, _) -> test_result1_of_test_result pth rslt) let assert_failure = OUnitAssert.assert_failure let assert_bool = OUnitAssert.assert_bool let ( @? ) = OUnitAssert.assert_bool let assert_string = OUnitAssert.assert_string let assert_command ?exit_code ?sinput ?foutput ?use_stderr ?env ?(verbose=false) prg args = let ctxt = let ctxt = get_test_context () in let conf' = Hashtbl.copy ctxt.OUnitTest.conf in OUnitConf.set ~origin:"OUnit.assert_command" conf' "verbose" (string_of_bool verbose); { ctxt with OUnitTest.test_logger = OUnitLogger.Test.create (OUnitLoggerStd.std_logger conf' OUnitLogger.shard_default) ctxt.OUnitTest.path; } in OUnitAssert.assert_command ?exit_code ?sinput ?foutput ?use_stderr ?env ~ctxt prg args let assert_equal ?cmp ?printer ?pp_diff ?msg a b = OUnitAssert.assert_equal ?cmp ?printer ?pp_diff ?msg a b let assert_raises ?msg exc f = OUnitAssert.assert_raises ?msg exc f let skip_if = OUnitAssert.skip_if let todo = OUnitAssert.todo let cmp_float ?epsilon f1 f2 = OUnitUtils.cmp_float ?epsilon f1 f2 let bracket pre f post () = OUnitTest.section_ctxt (get_test_context ()) (fun ctxt -> let fixture = OUnitBracket.create (fun _ -> pre ()) (fun fixture _ -> post fixture) ctxt in let () = f fixture in ()) let bracket_tmpfile ?prefix ?suffix ?mode gen () = OUnitTest.section_ctxt (get_test_context ()) (fun ctxt -> let fixture = OUnitBracket.bracket_tmpfile ?prefix ?suffix ?mode ctxt in gen fixture) let (>:) a b = test1_of_test (OUnitTest.(>:) a (test_of_test1 b)) let (>::) a b = test1_of_test (OUnitTest.(>::) a (fun _ -> b ())) let (>:::) a b = test1_of_test (OUnitTest.(>:::) a (List.map test_of_test1 b)) let test_decorate g tst = test1_of_test (OUnitTest.test_decorate (fun f -> let f1 = (fun () -> f (get_test_context ())) in let f1' = g f1 in (fun ctxt -> set_test_context ctxt; f1' (); reset_test_context ())) (test_of_test1 tst)) let test_filter ?skip lst test = let res = OUnitTest.test_filter ?skip lst (test_of_test1 test) in match res with | Some tst -> Some (test1_of_test tst) | None -> None let test_case_count tst = OUnitTest.test_case_count (test_of_test1 tst) let string_of_node nd = OUnitTest.string_of_node (node_of_node1 nd) let string_of_path pth = OUnitTest.string_of_path (List.map node_of_node1 pth) let test_case_paths tst = let lst = OUnitTest.test_case_paths (test_of_test1 tst) in List.map (List.map node1_of_node) lst let default_v1_conf ?(verbose=false) () = OUnitConf.default ~preset: [ "chooser", "simple"; "runner", "sequential"; "results_style_1_X", "true"; "verbose", (string_of_bool verbose); "output_file", "none"; ] () let perform_test logger1 tst = let logger = OUnitLogger.fun_logger (function | {OUnitLogger.event = OUnitLogger.GlobalEvent _} -> () | {OUnitLogger.event = OUnitLogger.TestEvent (path, test_event)} -> begin let path1 = path1_of_path path in match test_event with | OUnitLogger.EStart -> logger1 (EStart path1) | OUnitLogger.EEnd -> logger1 (EEnd path1) | OUnitLogger.EResult rslt -> logger1 (EResult (test_result1_of_test_result path rslt)) | OUnitLogger.ELog _ | OUnitLogger.ELogRaw _ -> () end) ignore in let conf = default_v1_conf () in list_result1_of_list_result (OUnitCore.perform_test conf logger (snd (OUnitRunner.choice conf)) (snd (OUnitChooser.choice conf)) (test_of_test1 tst)) let run_test_tt ?verbose test = let conf = default_v1_conf ?verbose () in list_result1_of_list_result (OUnitCore.run_test_tt conf (OUnitLoggerStd.create conf OUnitLogger.shard_default) (snd (OUnitRunner.choice conf)) (snd (OUnitChooser.choice conf)) (test_of_test1 test)) let run_test_tt_main ?(arg_specs=[]) ?(set_verbose=ignore) suite = let suite = test_of_test1 suite in let only_test = ref [] in let list_test = ref false in let verbose = ref false in let specs = [ "-verbose", Arg.Set verbose, " Rather than displaying dots while running the test, be more verbose."; "-only-test", Arg.String (fun str -> only_test := str :: !only_test), "path Run only the selected tests."; "-list-test", Arg.Set list_test, " List tests"; ] @ arg_specs in let () = Arg.parse (Arg.align specs) (fun x -> raise (Arg.Bad ("Bad argument : " ^ x))) ("usage: " ^ Sys.argv.(0) ^ " [options] [-only-test path]*") in let conf = default_v1_conf ~verbose:!verbose () in set_verbose (OUnitLoggerStd.verbose conf); if !list_test then begin List.iter (fun pth -> print_endline (OUnitTest.string_of_path pth)) (OUnitTest.test_case_paths suite); [] end else begin let nsuite = if !only_test = [] then suite else begin match OUnitTest.test_filter ~skip:true !only_test suite with | Some test -> test | None -> failwithf "Filtering test %s lead to no tests." (String.concat ", " !only_test) end in let test_results = OUnitCore.run_test_tt conf (OUnitLoggerStd.std_logger conf OUnitLogger.shard_default) (snd (OUnitRunner.choice conf)) (snd (OUnitChooser.choice conf)) nsuite in list_result1_of_list_result test_results end ounit-2.0.0/src/oUnit.mli 0000644 0001750 0001750 00000023356 12222142072 014564 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) (** Unit test building blocks @author Maas-Maarten Zeeman @author Sylvain Le Gall *) (** {2 Assertions} Assertions are the basic building blocks of unittests. *) (** Signals a failure. This will raise an exception with the specified string. @raise Failure signal a failure *) val assert_failure : string -> 'a (** Signals a failure when bool is false. The string identifies the failure. @raise Failure signal a failure *) val assert_bool : string -> bool -> unit (** Shorthand for assert_bool @raise Failure to signal a failure *) val ( @? ) : string -> bool -> unit (** Signals a failure when the string is non-empty. The string identifies the failure. @raise Failure signal a failure *) val assert_string : string -> unit (** [assert_command prg args] Run the command provided. @param exit_code expected exit code @param sinput provide this [char Stream.t] as input of the process @param foutput run this function on output, it can contains an [assert_equal] to check it @param use_stderr redirect [stderr] to [stdout] @param env Unix environment @param verbose if failed, dump stdout/stderr of the process to stderr @since 1.1.0 *) val assert_command : ?exit_code:Unix.process_status -> ?sinput:char Stream.t -> ?foutput:(char Stream.t -> unit) -> ?use_stderr:bool -> ?env:string array -> ?verbose:bool -> string -> string list -> unit (** [assert_equal expected real] Compares two values, when they are not equal a failure is signaled. @param cmp customize function to compare, default is [=] @param printer value printer, don't print value otherwise @param pp_diff if not equal, ask a custom display of the difference using [diff fmt exp real] where [fmt] is the formatter to use @param msg custom message to identify the failure @raise Failure signal a failure @version 1.1.0 *) val assert_equal : ?cmp:('a -> 'a -> bool) -> ?printer:('a -> string) -> ?pp_diff:(Format.formatter -> ('a * 'a) -> unit) -> ?msg:string -> 'a -> 'a -> unit (** Asserts if the expected exception was raised. @param msg identify the failure @raise Failure description *) val assert_raises : ?msg:string -> exn -> (unit -> 'a) -> unit (** {2 Skipping tests } In certain condition test can be written but there is no point running it, because they are not significant (missing OS features for example). In this case this is not a failure nor a success. Following functions allow you to escape test, just as assertion but without the same error status. A test skipped is counted as success. A test todo is counted as failure. *) (** [skip cond msg] If [cond] is true, skip the test for the reason explain in [msg]. For example [skip_if (Sys.os_type = "Win32") "Test a doesn't run on windows"]. @since 1.0.3 *) val skip_if : bool -> string -> unit (** The associated test is still to be done, for the reason given. @since 1.0.3 *) val todo : string -> unit (** {2 Compare Functions} *) (** Compare floats up to a given relative error. @param epsilon if the difference is smaller [epsilon] values are equal *) val cmp_float : ?epsilon:float -> float -> float -> bool (** {2 Bracket} A bracket is a functional implementation of the commonly used setUp and tearDown feature in unittests. It can be used like this: ["MyTestCase" >:: (bracket test_set_up test_fun test_tear_down)] *) (** [bracket set_up test tear_down] The [set_up] function runs first, then the [test] function runs and at the end [tear_down] runs. The [tear_down] function runs even if the [test] failed and help to clean the environment. *) val bracket: (unit -> 'a) -> ('a -> unit) -> ('a -> unit) -> unit -> unit (** [bracket_tmpfile test] The [test] function takes a temporary filename and matching output channel as arguments. The temporary file is created before the test and removed after the test. @param prefix see [Filename.open_temp_file] @param suffix see [Filename.open_temp_file] @param mode see [Filename.open_temp_file] @since 1.1.0 *) val bracket_tmpfile: ?prefix:string -> ?suffix:string -> ?mode:open_flag list -> ((string * out_channel) -> unit) -> unit -> unit (** {2 Constructing Tests} *) (** The type of test function *) type test_fun = unit -> unit (** The type of tests *) type test = TestCase of test_fun | TestList of test list | TestLabel of string * test (** Create a TestLabel for a test *) val (>:) : string -> test -> test (** Create a TestLabel for a TestCase *) val (>::) : string -> test_fun -> test (** Create a TestLabel for a TestList *) val (>:::) : string -> test list -> test (** Some shorthands which allows easy test construction. Examples: - ["test1" >: TestCase((fun _ -> ()))] => [TestLabel("test2", TestCase((fun _ -> ())))] - ["test2" >:: (fun _ -> ())] => [TestLabel("test2", TestCase((fun _ -> ())))] - ["test-suite" >::: ["test2" >:: (fun _ -> ());]] => [TestLabel("test-suite", TestSuite([TestLabel("test2", TestCase((fun _ -> ())))]))] *) (** [test_decorate g tst] Apply [g] to test function contains in [tst] tree. @since 1.0.3 *) val test_decorate : (test_fun -> test_fun) -> test -> test (** [test_filter paths tst] Filter test based on their path string representation. @param skip if set, just use [skip_if] for the matching tests. @since 1.0.3 *) val test_filter : ?skip:bool -> string list -> test -> test option (** {2 Retrieve Information from Tests} *) (** Returns the number of available test cases *) val test_case_count : test -> int (** Types which represent the path of a test *) type node = ListItem of int | Label of string type path = node list (** The path to the test (in reverse order). *) (** Make a string from a node *) val string_of_node : node -> string (** Make a string from a path. The path will be reversed before it is tranlated into a string *) val string_of_path : path -> string (** Returns a list with paths of the test *) val test_case_paths : test -> path list (** {2 Performing Tests} *) (** The possible results of a test *) type test_result = RSuccess of path | RFailure of path * string | RError of path * string | RSkip of path * string | RTodo of path * string (** Events which occur during a test run. *) type test_event = EStart of path (** A test start. *) | EEnd of path (** A test end. *) | EResult of test_result (** Result of a test. *) (** Results of a test run. *) type test_results = test_result list (** Perform the test, allows you to build your own test runner *) val perform_test : (test_event -> unit) -> test -> test_results (** A simple text based test runner. @param verbose print verbose message *) val run_test_tt : ?verbose:bool -> test -> test_results (** Main version of the text based test runner. It reads the supplied command line arguments to set the verbose level and limit the number of test to run. @param arg_specs add extra command line arguments @param set_verbose call a function to set verbosity @param fexit call a final function after test, by default exit 1. @version 1.1.0 *) val run_test_tt_main : ?arg_specs:(Arg.key * Arg.spec * Arg.doc) list -> ?set_verbose:(bool -> unit) -> test -> test_results val ounit2_of_ounit1 : test -> OUnit2.test ounit-2.0.0/src/oUnit2.ml 0000644 0001750 0001750 00000010615 12222142072 014467 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnitCore open OUnitTest let (>:) = OUnitTest.(>:) let (>::) = OUnitTest.(>::) let (>:::) = OUnitTest.(>:::) type test_ctxt = OUnitTest.ctxt type test_fun = OUnitTest.test_fun type test_length = OUnitTest.test_length type test = OUnitTest.test let test_case ?(length=Short) f = TestCase(length, f) let test_list lst = TestList lst type log_severity = OUnitLogger.log_severity let assert_failure = OUnitAssert.assert_failure let assert_bool = OUnitAssert.assert_bool let assert_string = OUnitAssert.assert_string (* Upgrade to OUnit v2, using logger. *) (* let assert_command = OUnitAssert.assert_command *) let assert_command ?exit_code ?sinput ?foutput ?use_stderr ?backtrace ?chdir ?env ~ctxt prg args = OUnitAssert.assert_command ?exit_code ?sinput ?foutput ?use_stderr ?backtrace ?chdir ?env ~ctxt prg args let assert_equal = OUnitAssert.assert_equal let assert_raises = OUnitAssert.assert_raises let skip_if = OUnitAssert.skip_if let todo = OUnitAssert.todo let cmp_float = OUnitUtils.cmp_float let bracket = OUnitBracket.create let bracket_tmpfile = OUnitBracket.bracket_tmpfile let bracket_tmpdir = OUnitBracket.bracket_tmpdir let with_bracket_chdir test_ctxt dn f = OUnitBracket.with_bracket test_ctxt (OUnitBracket.bracket_chdir dn) (fun () -> f) let non_fatal = OUnitTest.non_fatal let run_test_tt_main = OUnitCore.run_test_tt_main let logf ctxt log_severity fmt = OUnitLogger.Test.logf ctxt.test_logger log_severity fmt let in_testdata_dir ctxt path = OUnitTestData.in_testdata_dir ctxt.conf path let conf_wrap f name default help = let get = f name default help in fun ctxt -> get ctxt.conf module Conf = struct type 'a conf_t = string -> 'a -> Arg.doc -> test_ctxt -> 'a let make_string = conf_wrap OUnitConf.make_string let make_string_opt = conf_wrap OUnitConf.make_string_opt let make_int = conf_wrap OUnitConf.make_int let make_float = conf_wrap OUnitConf.make_float let make_bool = conf_wrap OUnitConf.make_bool let make_exec name = let get = OUnitConf.make_exec name in fun ctxt -> get ctxt.conf end ounit-2.0.0/src/oUnit2.mli 0000644 0001750 0001750 00000025664 12222142072 014652 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) (** Unit test building blocks (v2). @author Sylvain Le Gall *) (** {2 Types} *) (** Context of a test. *) type test_ctxt = OUnitTest.ctxt (** The type of test function. *) type test_fun = test_ctxt -> unit (** The type of test. *) type test = OUnitTest.test (** The expected length of the test. *) type test_length = OUnitTest.test_length (** {2 Assertions} Assertions are the basic building blocks of unittests. *) (** Signals a failure. This will raise an exception with the specified string. @raise Failure signal a failure *) val assert_failure : string -> 'a (** Signals a failure when bool is false. The string identifies the failure. @raise Failure signal a failure *) val assert_bool : string -> bool -> unit (** Signals a failure when the string is non-empty. The string identifies the failure. @raise Failure signal a failure *) val assert_string : string -> unit (** [assert_command prg args] Run the command provided. @param exit_code expected exit code @param sinput provide this [char Stream.t] as input of the process @param foutput run this function on output, it can contains an [assert_equal] to check it @param use_stderr redirect [stderr] to [stdout] @param backtrace Set OCAMLRUNPARAM=b @param chdir Chdir into a directory before running the command. @param env Unix environment @param verbose if a failed, dump stdout/stderr of the process to stderr *) val assert_command : ?exit_code:Unix.process_status -> ?sinput:char Stream.t -> ?foutput:(char Stream.t -> unit) -> ?use_stderr:bool -> ?backtrace:bool -> ?chdir:string -> ?env:string array -> ctxt:test_ctxt -> string -> string list -> unit (** [assert_equal expected real] Compares two values, when they are not equal a failure is signaled. @param cmp customize function to compare, default is [=] @param printer value printer, don't print value otherwise @param pp_diff if not equal, ask a custom display of the difference using [diff fmt exp real] where [fmt] is the formatter to use @param msg custom message to identify the failure @param ctxt if provided, always print expected and real value @raise Failure signal a failure *) val assert_equal : ?ctxt:test_ctxt -> ?cmp:('a -> 'a -> bool) -> ?printer:('a -> string) -> ?pp_diff:(Format.formatter -> ('a * 'a) -> unit) -> ?msg:string -> 'a -> 'a -> unit (** Asserts if the expected exception was raised. @param msg identify the failure @raise Failure description *) val assert_raises : ?msg:string -> exn -> (unit -> 'a) -> unit (** {2 Skipping tests } In certain condition test can be written but there is no point running it, because they are not significant (missing OS features for example). In this case this is not a failure nor a success. Following functions allow you to escape test, just as assertion but without the same error status. A test skipped is counted as success. A test todo is counted as failure. *) (** [skip cond msg] If [cond] is true, skip the test for the reason explain in [msg]. For example [skip_if (Sys.os_type = "Win32") "Test a doesn't run on windows"]. *) val skip_if : bool -> string -> unit (** The associated test is still to be done, for the reason given. *) val todo : string -> unit (** {2 Compare Functions} *) (** Compare floats up to a given relative error. @param epsilon if the difference is smaller [epsilon] values are equal *) val cmp_float : ?epsilon:float -> float -> float -> bool (** {2 Bracket} A bracket is a registered object with setUp and tearDown in unit tests. Data generated during the setUp will be automatically tearDown when the test ends. *) (** [bracket set_up tear_down test_ctxt] set up an object and register it to be tore down in [test_ctxt]. *) val bracket : (test_ctxt -> 'a) -> ('a -> test_ctxt -> unit) -> test_ctxt -> 'a (** [bracket_tmpfile test_ctxt] Create a temporary filename and matching output channel. The temporary file is removed after the test. @param prefix see [Filename.open_temp_file] @param suffix see [Filename.open_temp_file] @param mode see [Filename.open_temp_file] *) val bracket_tmpfile: ?prefix:string -> ?suffix:string -> ?mode:open_flag list -> test_ctxt -> (string * out_channel) (** [bracket_tmpdir test_ctxt] Create a temporary dirname. The temporary directory is removed after the test. @param prefix see [Filename.open_temp_file] @param suffix see [Filename.open_temp_file] *) val bracket_tmpdir: ?prefix:string -> ?suffix:string -> test_ctxt -> string (** [with_bracket_chdir test_ctxt dn f] change directory to [dn] during execution of function [f]. In order to [Sys.chdir], we need to take a lock to avoid other tests trying to do change the current directory at the same time. So this bracket is not directly accessible in order to use it only on shorter piece of code. *) val with_bracket_chdir: test_ctxt -> string -> (test_ctxt -> 'a) -> 'a (** {2 Constructing Tests} *) (** Create a TestLabel for a test *) val (>:) : string -> test -> test (** Create a TestLabel for a TestCase *) val (>::) : string -> test_fun -> test (** Create a TestLabel for a TestList *) val (>:::) : string -> test list -> test (** Generic function to create a test case. *) val test_case : ?length:test_length -> test_fun -> test (** Generic function to create a test list. *) val test_list : test list -> test (** Some shorthands which allows easy test construction. Examples: - ["test1" >: TestCase((fun _ -> ()))] => [TestLabel("test2", TestCase((fun _ -> ())))] - ["test2" >:: (fun _ -> ())] => [TestLabel("test2", TestCase((fun _ -> ())))] - ["test-suite" >::: ["test2" >:: (fun _ -> ());]] => [TestLabel("test-suite", TestSuite([TestLabel("test2", TestCase((fun _ -> ())))]))] *) (** {2 Performing Tests} *) (** Severity level for log. *) type log_severity = [ `Error | `Warning | `Info ] (** Log into OUnit logging system. *) val logf: test_ctxt -> log_severity -> ('a, unit, string, unit) format4 -> 'a (** Build a filename for a file that should be located in the test data dir. The test data dir, can be defined on the command line (preferably absolute) The default option is to locate it in topsrcdir/test/data. *) val in_testdata_dir: test_ctxt -> string list -> string (** [non_fatal ctxt f] Run [f] but if an exception is raised or an assert fails, don't stop, just register the result. The global test running result will mix in the non fatal result to determine the success or failure of the test. *) val non_fatal: test_ctxt -> (test_ctxt -> unit) -> unit (** Define command line options, environment variables and file configuration. This module helps to define configuration options that are translated to command line options et al. The name defined for the variable is: - should be a valid OCaml identifier - kept as is for use in configuration file. (foo_bar = "") - '_' are replaced by '-' and a leading '-' is added for command line (-foo "") - capitalized and prefixed by OUNIT_ for environment (OUNIT_FOO_BAR="") *) module Conf: sig (** The default type of function that create a configuration option of type 'a. *) type 'a conf_t = string -> 'a -> Arg.doc -> test_ctxt -> 'a (** [make_string name default help] Create a string configuration option with default value [default] and a short help string. The result of the partial application of the function can be used inside tests to be evaluated to a value. {[ let my_option = Conf.make_string "my_option" "the default" "A default option." let tests = "ATest" >:: (fun test_ctxt -> let option_value = my_option test_ctxt in ()) ]} *) val make_string: string conf_t (** Create a [string option] configuration option. See [!make_string]. *) val make_string_opt: (string option) conf_t (** Create an [int] configuration option. See [!make_string]. *) val make_int: int conf_t (** Create a [float] configuration option. See [!make_string]. *) val make_float: float conf_t (** Create a [bool] configuration option. See [!make_string]. *) val make_bool: bool conf_t (** [make_exec execname] Create a option to define an executable. *) val make_exec: string -> test_ctxt -> string end (** Main version of the text based test runner. It reads the supplied command line arguments to set the verbose level and limit the number of test to run. @param test the test suite to run. *) val run_test_tt_main : ?exit:(int -> unit) -> test -> unit ounit-2.0.0/src/oUnitAssert.ml 0000644 0001750 0001750 00000024200 12222142072 015562 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnitUtils open OUnitBracket open OUnitTest let skip_if b msg = if b then raise (Skip msg) let todo msg = raise (Todo msg) let assert_failure msg = raise (OUnit_failure msg) let assert_bool msg b = if not b then assert_failure msg let assert_string str = if not (str = "") then assert_failure str let assert_equal ?ctxt ?(cmp = ( = )) ?printer ?pp_diff ?msg expected actual = let get_error_string () = let res = buff_format_printf (fun fmt -> Format.pp_open_vbox fmt 0; begin match msg with | Some s -> Format.pp_open_box fmt 0; Format.pp_print_string fmt s; Format.pp_close_box fmt (); Format.pp_print_cut fmt () | None -> () end; begin match printer with | Some p -> Format.fprintf fmt "@[expected: @[%s@]@ but got: @[%s@]@]@," (p expected) (p actual) | None -> Format.fprintf fmt "@[not equal@]@," end; begin match pp_diff with | Some d -> Format.fprintf fmt "@[differences: %a@]@," d (expected, actual) | None -> () end; Format.pp_close_box fmt ()) in let len = String.length res in if len > 0 && res.[len - 1] = '\n' then String.sub res 0 (len - 1) else res in let logf fmt = match ctxt with | Some ctxt -> OUnitLogger.Test.logf ctxt.test_logger `Info fmt | None -> Printf.ksprintf ignore fmt in begin match msg with | Some str -> logf "%s" str; | _ -> () end; begin match printer with | Some p -> logf "Expected: %s" (p expected); logf "Actual: %s" (p actual) | _ -> () end; if not (cmp expected actual) then assert_failure (get_error_string ()) let assert_command ?(exit_code=Unix.WEXITED 0) ?(sinput=Stream.of_list []) ?(foutput=ignore) ?(use_stderr=true) ?(backtrace=true) ?chdir ?env ~ctxt prg args = OUnitTest.section_ctxt ctxt (fun ctxt -> let (fn_out, chn_out) = bracket_tmpfile ctxt in let cmd_print fmt = Format.pp_print_string fmt prg; List.iter (Format.fprintf fmt "@ %s") args in (* Start the process *) let in_write = Unix.dup (Unix.descr_of_out_channel chn_out) in let (out_read, out_write) = Unix.pipe () in let err = if use_stderr then in_write else Unix.stderr in let args = Array.of_list (prg :: args) in let env = let param = "OCAMLRUNPARAM" in let analyse_and_fix env = let arr = Array.copy env in let fixed = ref false in let new_var = ref "" in for i = 0 to (Array.length arr) - 1 do let really_starts, current_value = OUnitUtils.start_substr ~prefix:(param^"=") arr.(i) in if really_starts then begin (* Rewrite the params. *) if not (String.contains current_value 'b') then begin arr.(i) <- param^"="^current_value^"b" end; new_var := arr.(i); fixed := true end done; if !fixed then arr else Array.append arr [|param^"=b"|] in if backtrace then begin (* Analyse of the provided environment. *) match env with | Some env -> Some (analyse_and_fix env) | None -> Some (analyse_and_fix (Unix.environment ())) end else begin env end in let command_chdir, in_chdir = match chdir with | Some dn -> dn, fun f -> with_bracket ctxt (bracket_chdir dn) (fun () _ -> f ()) | None -> Sys.getcwd (), fun f -> f () in let pid = OUnitLogger.Test.logf ctxt.test_logger `Info "%s" (buff_format_printf (fun fmt -> Format.fprintf fmt "Starting command '%t'." cmd_print)); OUnitLogger.Test.logf ctxt.test_logger `Info "Working directory: %S" command_chdir; OUnitLogger.Test.logf ctxt.test_logger `Info "Environment: "; Array.iter (fun v -> OUnitLogger.Test.logf ctxt.test_logger `Info "%s" v) (match env with | Some e -> e | None -> Unix.environment ()); Unix.set_close_on_exec out_write; match env with | Some e -> in_chdir (fun () -> Unix.create_process_env prg args e out_read in_write err) | None -> in_chdir (fun () -> Unix.create_process prg args out_read in_write err) in let () = Unix.close out_read; Unix.close in_write in let () = (* Dump sinput into the process stdin *) let buff = " " in Stream.iter (fun c -> let _i : int = buff.[0] <- c; Unix.write out_write buff 0 1 in ()) sinput; Unix.close out_write in let _, real_exit_code = let rec wait_intr () = try Unix.waitpid [] pid with Unix.Unix_error (Unix.EINTR, _, _) -> wait_intr () in wait_intr () in (* Dump process output to stderr *) begin let chn = open_in fn_out in let buff = String.make 4096 'X' in let len = ref (-1) in while !len <> 0 do len := input chn buff 0 (String.length buff); OUnitLogger.Test.raw_printf ctxt.test_logger "%s" (String.sub buff 0 !len); done; close_in chn end; (* Check process status *) assert_equal ~msg:(buff_format_printf (fun fmt -> Format.fprintf fmt "@[Exit status of command '%t'@]" cmd_print)) ~printer:string_of_process_status exit_code real_exit_code; begin let chn = open_in fn_out in try foutput (Stream.of_channel chn) with e -> close_in chn; raise e end) let raises f = try f (); None with e -> Some e let assert_raises ?msg exn (f: unit -> 'a) = let pexn = Printexc.to_string in let get_error_string () = let str = Format.sprintf "expected exception %s, but no exception was raised." (pexn exn) in match msg with | None -> assert_failure str | Some s -> assert_failure (s^"\n"^str) in match raises f with | None -> assert_failure (get_error_string ()) | Some e -> assert_equal ?msg ~printer:pexn exn e ounit-2.0.0/src/oUnitBracket.ml 0000644 0001750 0001750 00000013130 12222142072 015674 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnitTest type t = (unit -> unit) list let create set_up tear_down test_ctxt = let fixture = set_up test_ctxt in let tear_down test_ctxt = tear_down fixture test_ctxt in OUnitShared.Mutex.with_lock test_ctxt.shared test_ctxt.tear_down_mutex (fun () -> test_ctxt.tear_down <- tear_down :: test_ctxt.tear_down); fixture let logf logger lvl fmt = OUnitLogger.Test.logf logger lvl fmt let bracket_tmpfile ?(prefix="ounit-") ?(suffix=".txt") ?mode test_ctxt = create (fun test_ctxt -> let suffix = "-"^(OUnitTest.get_shard_id test_ctxt)^suffix in let (fn, chn) = Filename.open_temp_file ?mode prefix suffix in logf test_ctxt.test_logger `Info "Created a temporary file: %S." fn; (fn, chn)) (fun (fn, chn) test_ctxt -> (try close_out chn with _ -> ()); try Sys.remove fn; logf test_ctxt.test_logger `Info "Removed a temporary file: %S." fn with _ -> ()) test_ctxt let bracket_tmpdir ?(prefix="ounit-") ?(suffix=".dir") test_ctxt = let max_attempt = 10 in let rec try_hard_mkdir attempt = if max_attempt = attempt then begin OUnitUtils.failwithf "Unable to create temporary directory after %d attempts." attempt end else begin try let suffix = "-"^(OUnitTest.get_shard_id test_ctxt)^suffix in let tmpdn = Filename.temp_file prefix suffix in Sys.remove tmpdn; Unix.mkdir tmpdn 0o755; tmpdn with Unix.Unix_error (Unix.EEXIST, "mkdir", _) -> try_hard_mkdir (max_attempt + 1) end in create (fun test_ctxt -> let tmpdn = try_hard_mkdir 0 in logf test_ctxt.test_logger `Info "Create a temporary directory: %S." tmpdn; tmpdn) (fun tmpdn test_ctxt -> let log_delete fn = logf test_ctxt.test_logger `Info "Delete in a temporary directory: %S." fn in let safe_run f a = try f a with _ -> () in let rec rmdir fn = Array.iter (fun bn -> let fn' = Filename.concat fn bn in let is_dir = try Sys.is_directory fn' with _ -> false in if is_dir then begin rmdir fn'; safe_run Unix.rmdir fn'; log_delete fn' end else begin safe_run Sys.remove fn'; log_delete fn' end) (try Sys.readdir fn with _ -> [||]) in rmdir tmpdn; safe_run Unix.rmdir tmpdn; log_delete tmpdn) test_ctxt let chdir_mutex = OUnitShared.Mutex.create OUnitShared.ScopeProcess let bracket_chdir dir test_ctxt = let () = OUnitLogger.infof test_ctxt.logger "Change directory to %S" dir; in let () = try OUnitShared.Mutex.lock test_ctxt.shared chdir_mutex; with OUnitShared.Lock_failure -> failwith "Trying to do a nested chdir." in let cur_pwd = Sys.getcwd () in create (fun test_ctxt -> Unix.chdir dir) (fun () test_ctxt -> Unix.chdir cur_pwd; OUnitShared.Mutex.unlock test_ctxt.shared chdir_mutex) test_ctxt let with_bracket test_ctxt bracket f = section_ctxt test_ctxt (fun test_ctxt -> let res = bracket test_ctxt in f res test_ctxt) ounit-2.0.0/src/oUnitCache.ml 0000644 0001750 0001750 00000006767 12222142072 015346 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnitTest type cache = OUnitTest.result MapPath.t let cache_filename = OUnitConf.make_string_subst_opt "cache_filename" (* TODO: oUnit-$(name).cache *) (Some (Filename.concat OUnitUtils.buildir "oUnit-$(suite_name).cache")) "Cache file to store previous results." let default = MapPath.empty let load conf = match cache_filename conf with | Some fn -> begin try let chn = open_in fn in let cache : cache = try Marshal.from_channel chn with e -> default in close_in chn; cache with _ -> default end | None -> default let dump conf cache = match cache_filename conf with | Some fn -> begin try let chn = open_out fn in Marshal.to_channel chn cache []; close_out chn with _ -> () end | None -> () let get_result path cache = try Some (MapPath.find path cache) with Not_found -> None let add_result path result cache = MapPath.add path result cache ounit-2.0.0/src/oUnitCheckEnv.ml 0000644 0001750 0001750 00000006472 12222142072 016022 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) (* Check environment after and before tests, to check isolation. *) open OUnitTest open OUnitAssert type t = { pwd: string; env: string array; } let create () = { pwd = Sys.getcwd (); env = Unix.environment (); } module EnvElement = struct type t = string let pp_printer = Format.pp_print_string let compare = String.compare let pp_print_sep = OUnitDiff.pp_comma_separator end module SetEnv = OUnitDiff.SetMake(EnvElement) let check test_ctxt t = let t' = create () in List.iter (fun f -> non_fatal test_ctxt (fun _ -> f ())) [ (fun () -> assert_equal ~msg:"Current working dir (check env)." ~printer:(fun s -> s) t.pwd t'.pwd); (fun () -> let convert t = SetEnv.of_list (Array.to_list t.env) in SetEnv.assert_equal ~msg:"Environment (check env)." (convert t) (convert t')); ] ounit-2.0.0/src/oUnitChooser.ml 0000644 0001750 0001750 00000012031 12222142072 015722 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) (** Heuristic to pick a test to run. @author Sylvain Le Gall *) open OUnitTest type t = { tests_planned: path list; tests_running: path list; tests_passed: result_list; cache: OUnitCache.cache; } type choice = | ChooseToSkip of path | ChooseToPostpone | Choose of path | NoChoice let string_of_choice = function | ChooseToSkip path -> Printf.sprintf "ChooseToSkip %S" (string_of_path path) | ChooseToPostpone -> "ChooseToPostpone" | Choose path -> Printf.sprintf "Choose %S" (string_of_path path) | NoChoice -> "NoChoice" type chooser = t -> choice (** Most simple heuristic, just pick the first test. *) let simple t = match t.tests_planned with | hd :: _ -> Choose hd | [] -> NoChoice module Plugin = OUnitPlugin.Make (struct type t = chooser let name = "chooser" let conf_help = "Select the method to choose tests to run." let default_name = "simple" let default_value = simple end) include Plugin let allskip t = match t.tests_planned with | hd :: _ -> ChooseToSkip hd | [] -> NoChoice let failfirst t = let was_successful = OUnitResultSummary.was_successful in let rec find_failing = function | path :: tl -> begin match OUnitCache.get_result path t.cache with | Some result -> (* Find the first formerly failing test. *) if was_successful [path, result, None] then find_failing tl else Choose path | None -> Choose path end | [] -> begin let wait_results_running = List.fold_left (fun wait path -> match OUnitCache.get_result path t.cache with | Some result -> (not (was_successful [path, result, None])) || wait | None -> (* No former result, we need the result of * this test. *) true) false t.tests_running in if wait_results_running then (* We need more data about currently running tests. *) ChooseToPostpone else if was_successful t.tests_passed then (* All tests that were red has become green, continue. *) simple t else (* Some tests still fail, skip the rest. *) allskip t end in find_failing t.tests_planned let () = register "failfirst" ~-1 failfirst ounit-2.0.0/src/oUnitConf.ml 0000644 0001750 0001750 00000026610 12222142072 015215 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnitUtils exception Parse_error of string type conf = OUnitPropList.t type metadata = { help: string; get_print: conf -> string; parse_set: string -> conf -> unit; cli: conf -> (string * Arg.spec * string) list; } let metaconf = Hashtbl.create 13 let check_variable_name str = let () = if String.length str = 0 then failwith "'' is not a valid name." in let () = match str.[0] with | '0' .. '9' | '_' -> failwithf "%S is not a valid variable name. It must not start with %C." str str.[0] | _ -> () in String.iter (function | 'A' .. 'Z' | 'a' .. 'z' | '_' | '0' .. '9' -> () | c -> failwithf "%S is not a valid variable name. It must not contain %C." str c) str let cli_name name = let cli_name = "-" ^ name in for i = 1 to String.length name do match cli_name.[i] with | '_' -> cli_name.[i] <- '-' | _ -> () done; cli_name let subst conf extra_subst str = let substitutions = Hashtbl.create (Hashtbl.length metaconf) in let () = (* Fill the substitutions table. *) Hashtbl.iter (fun name metadata -> Hashtbl.add substitutions name (metadata.get_print conf)) metaconf; List.iter (fun (k, v) -> Hashtbl.add substitutions k v) extra_subst in let buff = Buffer.create (String.length str) in Buffer.add_substitute buff (fun var -> try Hashtbl.find substitutions var with Not_found -> failwithf "Unknown substitution variable %S in %S." var str) str; Buffer.contents buff let make ~name ~parse ~print ~default ~help ~fcli () = let () = check_variable_name name; if Hashtbl.mem metaconf name then failwithf "Duplicate definition for configuration variable %S." name in let set, get = OUnitPropList.new_property default in let parse_set str conf = set conf (parse str) in let get_print conf = print (get conf) in Hashtbl.add metaconf name {help = help; get_print = get_print; parse_set = parse_set; cli = (fun conf -> fcli (get conf) (set conf))}; get let make_string name default help = make ~name ~parse:(fun s -> s) ~print:(fun s -> s) ~default ~help ~fcli: (fun get set -> [cli_name name, Arg.String set, "str "^help]) () let make_string_subst name default help = let get = make_string name default help in (fun ?(extra_subst=[]) conf -> subst conf extra_subst (get conf)) let make_string_opt name default help = make ~name ~parse: (function | "none" -> None | str -> Some str) ~print: (function | Some x -> x | None -> "none") ~default ~help ~fcli: (fun get set -> [cli_name name, Arg.String (fun str -> set (Some str)), "str "^help; cli_name ("no_"^name), Arg.Unit (fun () -> set None), Printf.sprintf " Reset value of %s." name]) () let make_string_subst_opt name default opt = let get = make_string_opt name default opt in (fun ?(extra_subst=[]) conf -> match get conf with | Some str -> Some (subst conf extra_subst str) | None -> None) let make_int name default help = make ~name ~parse: (fun str -> try int_of_string str with Failure _ -> raise (Parse_error (Printf.sprintf "%S is not an integer." str))) ~print:string_of_int ~default ~help ~fcli: (fun get set -> [cli_name name, Arg.Int set, "i "^help]) () let make_float name default help = make ~name ~parse: (fun str -> try float_of_string str with Failure _ -> raise (Parse_error (Printf.sprintf "%S is not a float." str))) ~print:string_of_float ~default ~help ~fcli: (fun get set -> [cli_name name, Arg.Float set, "f "^help]) () let make_bool name default help = make ~name ~parse: (fun str -> try bool_of_string str with Failure _ -> raise (Parse_error (Printf.sprintf "%S is not a boolean (true or false)." str))) ~print:string_of_bool ~default ~help ~fcli: (fun get set -> [cli_name name, Arg.Bool set, "{true|false} "^help]) () let make_enum name get_enums default help = let parse str = let enum_lst = get_enums () in if not (List.exists (fun (str', _) -> str = str') enum_lst) then raise (Parse_error (Printf.sprintf "%S is not an allowed value for %s." str name)); str in let get = make ~name ~parse ~print:(fun s -> s) ~default ~help ~fcli: (fun get set -> [cli_name name, Arg.Symbol (List.map fst (get_enums ()), set), " "^help]) () in fun conf -> try get conf, List.assoc (get conf) (get_enums ()) with Not_found -> failwithf "Enums list for %s has changed during execution." name let make_exec name = let default = let pwd = Sys.getcwd () in let bn = Filename.concat pwd name in if Sys.file_exists (bn^".native") then bn^".native" else if Sys.file_exists (bn^".byte") then bn^".byte" else name in make_string name default (Printf.sprintf "Executable %s." name) let set ~origin conf name value = try (Hashtbl.find metaconf name).parse_set value conf with | Not_found -> failwithf "Variable %S is not defined in the application.\n%s" name origin | Parse_error str -> failwith (str ^ "\n" ^ origin) let file_parse conf fn = let parse lineno line = let origin = Printf.sprintf "File \"%s\", line %d." fn lineno in match trim (trim_comment line) with | "" -> () | str -> begin let name, value = try Scanf.sscanf str "%s = %S" (fun name value -> name, value) with Scanf.Scan_failure _ -> begin try Scanf.sscanf str "%s = %s" (fun name value -> name, value) with Scanf.Scan_failure _ -> failwithf "Unparseable line: %s\n%s" line origin end in set ~origin conf name value end in let chn = open_in fn in let lineno = ref 0 in try while true do let line = input_line chn in incr lineno; parse !lineno line done; () with | End_of_file -> close_in chn | e -> close_in chn; raise e let env_parse conf = let parse name = let env_name = "OUNIT_" ^ (String.uppercase name) in try let value = Sys.getenv env_name in (* Check and translate double quoted variable. *) let value = try Scanf.sscanf value "%S" (fun s -> s) with Scanf.Scan_failure _ -> value in let origin = Printf.sprintf "Environment variable %s=%S." env_name value in set ~origin conf name value with Not_found -> () in Hashtbl.iter (fun name _ -> parse name) metaconf let cli_parse ?argv extra_specs conf = let specs = Hashtbl.fold (fun name metadata lst -> let cli_lst = match metadata.cli conf with | (key, spec, doc) :: tl -> (key, spec, doc ^ (Printf.sprintf " (default: %s)" (metadata.get_print conf))) :: tl | [] -> [] in cli_lst @ lst) metaconf [] in let all_specs = Arg.align ([ "-conf", Arg.String (file_parse conf), "fn Read configuration file." ] @ (List.sort Pervasives.compare specs) @ extra_specs) in let arg_parse = match argv with | Some arr -> Arg.parse_argv ~current:(ref 0) arr | None -> Arg.parse in arg_parse all_specs (fun x -> raise (Arg.Bad ("Unexpected argument: " ^ x))) ("usage: " ^ Sys.argv.(0) ^ " options*") let default ?(preset=[]) () = let conf = OUnitPropList.create () in List.iter (fun (name, value) -> set ~origin:"Preset by program." conf name value) preset; conf (** Load test options from file, environment and command line (in this order). Not that [extra_specs] is here for historical reason, better use [make] to create command line options. *) let load ?preset ?argv extra_specs = let conf = default ?preset () in if Sys.file_exists "ounit.conf" then file_parse conf "ounit.conf"; env_parse conf; cli_parse ?argv extra_specs conf; conf let dump conf = Hashtbl.fold (fun name metadata lst -> (name, metadata.get_print conf) :: lst) metaconf [] ounit-2.0.0/src/oUnitCore.ml 0000644 0001750 0001750 00000014225 12222142072 015217 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open OUnitUtils open OUnitTest open OUnitLogger (* Plugin initialisation. *) let () = OUnitRunnerProcesses.init () (* * Types and global states. *) (* Run all tests, report starts, errors, failures, and return the results *) let perform_test conf logger runner chooser test = let rec flatten_test path acc = function | TestCase(l, f) -> (path, l, f) :: acc | TestList (tests) -> fold_lefti (fun acc t cnt -> flatten_test ((ListItem cnt)::path) acc t) acc tests | TestLabel (label, t) -> flatten_test ((Label label)::path) acc t in let test_cases = List.rev (flatten_test [] [] test) in runner conf logger chooser test_cases (* A simple (currently too simple) text based test runner *) let run_test_tt conf logger runner chooser test = let () = Printexc.record_backtrace true in let () = (* TODO: move into perform test. *) List.iter (fun (k, v) -> OUnitLogger.report logger (GlobalEvent (GConf (k, v)))) (OUnitConf.dump conf) in (* Now start the test *) let running_time, test_results = time_fun (perform_test conf logger runner chooser) test in (* TODO: move into perform test. *) (* Print test report *) OUnitLogger.report logger (GlobalEvent (GResults (running_time, test_results, OUnitTest.test_case_count test))); (* Reset logger. *) OUnitLogger.close logger; (* Return the results possibly for further processing *) test_results (* Test-only override. *) let run_test_tt_main_conf = ref (fun ?(preset=[]) ?argv extra_specs -> OUnitConf.load ?argv ~preset:(OUnitChooser.preset (OUnitRunner.preset preset)) extra_specs) let suite_name = OUnitConf.make_string "suite_name" "anon" "The name of the test suite running." (* Call this one to act as your main() function. *) let run_test_tt_main ?(exit=Pervasives.exit) suite = let only_test = ref [] in let list_test = ref false in let extra_specs = [ "-only-test", Arg.String (fun str -> only_test := str :: !only_test), "path Run only the selected tests."; "-list-test", Arg.Set list_test, " List tests"; ] in let preset = match suite with | OUnitTest.TestLabel (suite_name, _) -> ["suite_name", suite_name] | OUnitTest.TestCase _ | OUnitTest.TestList _ -> [] in let conf = !run_test_tt_main_conf ~preset extra_specs in if !list_test then begin List.iter (fun pth -> print_endline (OUnitTest.string_of_path pth)) (OUnitTest.test_case_paths suite) end else begin let nsuite = if !only_test = [] then suite else begin match OUnitTest.test_filter ~skip:true !only_test suite with | Some test -> test | None -> failwithf "Filtering test %s lead to no tests." (String.concat ", " !only_test) end in let logger = OUnitLogger.combine [ OUnitLoggerStd.create conf shard_default; OUnitLoggerHTML.create conf; OUnitLoggerJUnit.create conf; ] in let runner_name, runner = OUnitRunner.choice conf in let chooser_name, chooser = OUnitChooser.choice conf in let test_results = OUnitLogger.infof logger "Runner: %s" runner_name; OUnitLogger.infof logger "Chooser: %s" chooser_name; run_test_tt conf logger runner chooser nsuite in if not (OUnitResultSummary.was_successful test_results) then exit 1 end ounit-2.0.0/src/oUnitDiff.ml 0000644 0001750 0001750 00000013701 12222142072 015175 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) open Format module type DIFF_ELEMENT = sig type t val pp_printer: Format.formatter -> t -> unit val compare: t -> t -> int val pp_print_sep: Format.formatter -> unit -> unit end module type S = sig type e type t val compare: t -> t -> int val pp_printer: Format.formatter -> t -> unit val pp_diff: Format.formatter -> (t * t) -> unit val assert_equal: ?msg:string -> t -> t -> unit val of_list: e list -> t end let assert_equal ?msg compare pp_printer pp_diff exp act = OUnitAssert.assert_equal ~cmp:(fun t1 t2 -> (compare t1 t2) = 0) ~printer:(fun t -> let buff = Buffer.create 13 in let fmt = formatter_of_buffer buff in pp_printer fmt t; pp_print_flush fmt (); Buffer.contents buff) ~pp_diff ?msg exp act module SetMake (D: DIFF_ELEMENT) : S with type e = D.t = struct module Set = Set.Make(D) type e = D.t type t = Set.t let compare = Set.compare let pp_printer fmt t = let first = ref true in pp_open_box fmt 0; Set.iter (fun e -> if not !first then D.pp_print_sep fmt (); D.pp_printer fmt e; first := false) t; pp_close_box fmt () let pp_diff fmt (t1, t2) = let first = ref true in let print_list c t = Set.iter (fun e -> if not !first then D.pp_print_sep fmt (); pp_print_char fmt c; D.pp_printer fmt e; first := false) t in pp_open_box fmt 0; print_list '+' (Set.diff t2 t1); print_list '-' (Set.diff t1 t2); pp_close_box fmt () let assert_equal ?msg exp act = assert_equal ?msg compare pp_printer pp_diff exp act let of_list lst = List.fold_left (fun acc e -> Set.add e acc) Set.empty lst end module ListSimpleMake (D: DIFF_ELEMENT) : S with type e = D.t and type t = D.t list = struct type e = D.t type t = e list let rec compare t1 t2 = match t1, t2 with | e1 :: tl1, e2 :: tl2 -> begin match D.compare e1 e2 with | 0 -> compare tl1 tl2 | n -> n end | [], [] -> 0 | _, [] -> -1 | [], _ -> 1 let pp_print_gen pre fmt t = let first = ref true in pp_open_box fmt 0; List.iter (fun e -> if not !first then D.pp_print_sep fmt (); fprintf fmt "%s%a" pre D.pp_printer e; first := false) t; pp_close_box fmt () let pp_printer fmt t = pp_print_gen "" fmt t let pp_diff fmt (t1, t2) = let rec pp_diff' n t1 t2 = match t1, t2 with | e1 :: tl1, e2 :: tl2 -> begin match D.compare e1 e2 with | 0 -> pp_diff' (n + 1) tl1 tl2 | _ -> fprintf fmt "element number %d differ (%a <> %a)" n D.pp_printer e1 D.pp_printer e2 end | [], [] -> () | [], lst -> fprintf fmt "at end,@ "; pp_print_gen "+" fmt lst | lst, [] -> fprintf fmt "at end,@ "; pp_print_gen "-" fmt lst in pp_open_box fmt 0; pp_diff' 0 t1 t2; pp_close_box fmt () let assert_equal ?msg exp act = assert_equal ?msg compare pp_printer pp_diff exp act let of_list lst = lst end let pp_comma_separator fmt () = fprintf fmt ",@ " ounit-2.0.0/src/oUnitDiff.mli 0000644 0001750 0001750 00000011400 12222142072 015340 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) (** Unit tests for collection of elements This module allows to define a more precise way to display differences between collection of elements. When collection differ, the tester is interested by what are the missing/extra elements. This module provides a [diff] operation to spot the difference quickly between two sets of elements. Example: {[ open OUnit;; module EInt = struct type t = int let compare = ( - ) let pp_printer = Format.pp_print_int let pp_print_sep = OUnitDiff.pp_comma_separator end module ListInt = OUnitDiff.ListSimpleMake(EInt);; let test_diff () = ListInt.assert_equal [1; 2; 3; 4; 5] [1; 2; 5; 4] ;; let _ = run_test_tt_main ("test_diff" >:: test_diff) ;; ]} when run this test outputs: {[ OUnit: expected: 1, 2, 3, 4, 5 but got: 1, 2, 5, 4 differences: element number 2 differ (3 <> 5) ]} @since 1.1.0 @author Sylvain Le Gall *) (** {2 Signatures} *) (** Definition of an element *) module type DIFF_ELEMENT = sig (** Type of an element *) type t (** Pretty printer for an element *) val pp_printer : Format.formatter -> t -> unit (** Element comparison *) val compare : t -> t -> int (** Pretty print element separator *) val pp_print_sep : Format.formatter -> unit -> unit end (** Definition of standard operations *) module type S = sig (** Type of an element *) type e (** Type of a collection of element *) type t (** Compare a collection of element *) val compare : t -> t -> int (** Pretty printer a collection of element *) val pp_printer : Format.formatter -> t -> unit (** Pretty printer for collection differences *) val pp_diff : Format.formatter -> t * t -> unit (** {!assert_equal} with [~diff], [~cmp] and [~printer] predefined for this collection events *) val assert_equal : ?msg:string -> t -> t -> unit (** Create [t] using of list *) val of_list : e list -> t end (** {2 Implementations} *) (** Collection of elements based on a Set, elements order doesn't matter *) module SetMake : functor (D : DIFF_ELEMENT) -> S with type e = D.t (** Collection of elements based on a List, order matters but difference display is very simple. It stops at the first element which differs. *) module ListSimpleMake : functor (D: DIFF_ELEMENT) -> S with type e = D.t and type t = D.t list val pp_comma_separator : Format.formatter -> unit -> unit ounit-2.0.0/src/oUnitLogger.ml 0000644 0001750 0001750 00000015427 12222142072 015553 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) (* Logger for information and various OUnit events. *) open OUnitUtils (* See OUnit.mli. *) type position = { filename: string; line: int; } (** See OUnit.mli. *) type log_severity = [`Error | `Warning | `Info] (** See OUnit.mli. *) type 'result test_event = | EStart | EEnd | EResult of 'result | ELog of log_severity * string | ELogRaw of string type ('path, 'result) result_full = ('path * 'result * position option) (** Events which occur at the global level. *) type ('path, 'result) global_event = | GConf of string * string (** Dump a configuration options. *) | GLog of log_severity * string | GStart (** Start running the tests. *) | GEnd (** Finish running the tests. *) | GResults of (float * ('path, 'result) result_full list * int) type ('path, 'result) log_event_t = | GlobalEvent of ('path, 'result) global_event | TestEvent of 'path * 'result test_event type ('path, 'result) log_event = { shard: string; timestamp: float; event: ('path, 'result) log_event_t; } type ('path, 'result) logger = { lshard: string; fwrite: ('path, 'result) log_event -> unit; fpos: unit -> position option; fclose: unit -> unit; } let shard_default = OUnitUtils.shardf 0 let string_of_event ev = let spf fmt = Printf.sprintf fmt in let string_of_log_severity = function | `Error -> "`Error" | `Warning -> "`Warning" | `Info -> "`Info" in match ev with | GlobalEvent e -> begin match e with | GConf (k, v) -> spf "GConf (%S, %S)" k v | GLog (lvl, s) -> spf "GLog (%s, %S)" (string_of_log_severity lvl) s | GStart -> "GStart" | GEnd -> "GEnd" | GResults _ -> "GResults" end | TestEvent (path, e) -> begin match e with | EStart -> "EStart" | EEnd -> "EEnd" | EResult result -> "EResult (_)" | ELog (lvl, str) -> spf "ELog (%s, %S)" (string_of_log_severity lvl) str | ELogRaw str -> spf "ELogRaw %S" str end let null_logger = { lshard = shard_default; fwrite = ignore; fpos = (fun () -> None); fclose = ignore; } let fun_logger fwrite fclose = { lshard = shard_default; fwrite = (fun log_ev -> fwrite log_ev); fpos = (fun () -> None); fclose = fclose; } let post_logger fpost = let data = ref [] in let fwrite ev = data := ev :: !data in let fclose () = fpost (List.rev !data) in { lshard = shard_default; fwrite = fwrite; fpos = (fun () -> None); fclose = fclose; } let set_shard shard logger = {logger with lshard = shard} let report logger ev = logger.fwrite { shard = logger.lshard; timestamp = now (); event = ev; } let infof logger fmt = Printf.ksprintf (fun str -> report logger (GlobalEvent (GLog (`Info, str)))) fmt let warningf logger fmt = Printf.ksprintf (fun str -> report logger (GlobalEvent (GLog (`Warning, str)))) fmt let errorf logger fmt = Printf.ksprintf (fun str -> report logger (GlobalEvent (GLog (`Error, str)))) fmt let position logger = logger.fpos () let close logger = logger.fclose () let combine lst = let rec fpos = function | logger :: tl -> begin match position logger with | Some _ as pos -> pos | None -> fpos tl end | [] -> None in let lshard = match lst with hd :: _ -> hd.lshard | [] -> shard_default in { lshard = lshard; fwrite = (fun log_ev -> List.iter (fun logger -> logger.fwrite log_ev) lst); fpos = (fun () -> fpos lst); fclose = (fun () -> List.iter (fun logger -> close logger) (List.rev lst)); } module Test = struct type 'result t = 'result test_event -> unit let create logger path = fun ev -> logger.fwrite { shard = logger.lshard; timestamp = now (); event = TestEvent (path, ev) } let raw_printf t fmt = Printf.ksprintf (fun s -> t (ELogRaw s)) fmt let logf t lvl fmt = Printf.ksprintf (fun s -> t (ELog (lvl, s))) fmt end ounit-2.0.0/src/oUnitLoggerHTML.ml 0000644 0001750 0001750 00000022343 12222142072 016233 0 ustar gildor gildor (**************************************************************************) (* The OUnit library *) (* *) (* Copyright (C) 2002-2008 Maas-Maarten Zeeman. *) (* Copyright (C) 2010 OCamlCore SARL *) (* Copyright (C) 2013 Sylvain Le Gall *) (* *) (* The package OUnit is copyright by Maas-Maarten Zeeman, OCamlCore SARL *) (* and Sylvain Le Gall. *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining *) (* a copy of this document and the OUnit software ("the Software"), to *) (* deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, *) (* sublicense, and/or sell copies of the Software, and to permit persons *) (* to whom the Software is furnished to do so, subject to the following *) (* conditions: *) (* *) (* The above copyright notice and this permission notice shall be *) (* included in all copies or substantial portions of the Software. *) (* *) (* The Software is provided ``as is'', without warranty of any kind, *) (* express or implied, including but not limited to the warranties of *) (* merchantability, fitness for a particular purpose and noninfringement. *) (* In no event shall Maas-Maarten Zeeman be liable for any claim, damages *) (* or other liability, whether in an action of contract, tort or *) (* otherwise, arising from, out of or in connection with the Software or *) (* the use or other dealings in the software. *) (* *) (* See LICENSE.txt for details. *) (**************************************************************************) (* HTML logger for OUnit. *) open OUnitLogger open OUnitUtils open OUnitTest open OUnitResultSummary let html_escaper str = let buffer = Buffer.create (String.length str) in let addc = Buffer.add_char buffer in let addse se = addc '&'; Buffer.add_string buffer se; addc ';' in String.iter (function | '"' -> addse "quot" | '&' -> addse "amp" | '<' -> addse "lt" | '>' -> addse "gt" (* | 'Œ' -> addse "OElig" | 'œ' -> addse "oelig" | 'Š' -> addse "Scaron" | 'š' -> addse "scaron" | 'Ÿ' -> addse "Yuml" | 'ˆ' -> addse "circ" | '˜' -> addse "tilde" | ' ' -> addse "ensp" | ' ' -> addse "emsp" | ' ' -> addse "thinsp" | '–' -> addse "ndash" | '—' -> addse "mdash" | '‘' -> addse "lsquo" | '’' -> addse "rsquo" | '‚' -> addse "sbquo" | '“' -> addse "ldquo" | '”' -> addse "rdquo" | '„' -> addse "bdquo" | '†' -> addse "dagger" | '‡' -> addse "Dagger" | '‰' -> addse "permil" | '‹' -> addse "lsaquo" | '›' -> addse "rsaquo" | '€' -> addse "euro" *) | '\'' -> addse "#39" | c -> addc c) str; Buffer.contents buffer let render conf dn events = let smr = OUnitResultSummary.of_log_events conf events in let () = if not (Sys.file_exists dn) then Unix.handle_unix_error (fun () -> Unix.mkdir dn 0o755) () in let chn = open_out (Filename.concat dn "oUnit.css") in let () = output_string chn OUnitLoggerHTMLData.oUnit_css; close_out chn in let chn = open_out (Filename.concat dn "oUnit.js") in let () = output_string chn OUnitLoggerHTMLData.oUnit_js; close_out chn in let chn = open_out (Filename.concat dn "index.html") in let printf fmt = Printf.fprintf chn fmt in printf "\