autodoc.git / traditional_manual / chapter_21.html

version» Context lines:

autodoc.git/traditional_manual/chapter_21.html:1:   <!doctype html><html><head><title>Pike Reference Manual</title>   <meta charset='utf-8'></head> - <body><dl><dt><h1 class='header'>21. Pike Test Suite</h1></dt><dd><p><span class='fixme'>FIXME: The goals of the test suite and an overview of it</span></p></dd> + <body><dl><dt><h1 class='header'>21. Writing Pike Modules</h1></dt><dd><p> +  This chapter will discuss how to extend Pike by writing +  modules. There are two major ways to write modules, either they +  can be written in Pike, or they can be written in C. Generally, +  modules can be seen as a collection of pike programs and +  functions. This is, obviously, handy for grouping related programs +  and functions. +  </p><p> +  A pike module is actually a pike program which is cloned by the +  pike compiler during compilation of programs. This means that all +  lfuns that can be used in a pike program also can be used in a +  module. This is, for instance, useful for overloading the +  operators of a module to obtain a certain behaviour. Bear in mind +  that variables defined on a module-wide bases are shared among all +  clones of programs in the module. +  <span class='fixme'>FIXME: Explain difference between .pmod and .pike</span> +  </p><p> +  Pike searches for modules in the module path as defined during the +  compilation of a pike program. The module-path defaults to contain +  the directory where all standard pike modules are installed. This +  can be altered using +  <code>/master.CompatResolver()-&gt;add_module_path()</code> in a +  program or by letting the environment variable +  <b>PIKE_MODULE_PATH</b> contain a colon-separated list of +  directories to be searched for modules before looking at the +  default location. +  </p></dd>   <dt><a name='21.1'></a> - <h2 class='header'>21.1. Running Tests</h2></dt> - <dd><p>The most common way of running tests from the test suite is to -  use the top level make target <tt>verify</tt> which installs a test -  Pike in the build directory and use it while running the entire test -  suite. The following test-related make targets are defined in the top -  level make file.</p><dl> - <dt>tinstall</dt> - <dd>Makes and installs a test Pike binary in the build directory. If -  a test Pike binary was already installed, it will first be -  removed.</dd> - <dt>just_verify</dt> - <dd>Runs the test suite with the flags "<tt>-F -a -v</tt>", without -  installing a new test Pike binary.</dd> - <dt>testsuites</dt> - <dd>Creates testsuite files in the build tree from the -  testsuite.in-files in the src/ and lib/ trees.</dd> - <dt>verify</dt> - <dd>Runs the <tt>testsuites</tt>, <tt>tinstall</tt> and -  <tt>just_verify</tt> targets.</dd> - <dt>verify_installed</dt> - <dd>Runs the test suit with the flags "<tt>-F -a -v</tt>", with the -  Pike binary installed on the system.</dd> - <dt>check</dt> - <dd>Alias for the <tt>verify</tt> make target.</dd> - <dt>sure</dt> - <dd>Alias for the <tt>verify</tt> make target.</dd> - <dt>verbose_verify</dt> - <dd>Runs the <tt>tinstall</tt> make target and then runs the test -  suite with the flags "<tt>-F -v -v -a</tt>".</dd> - <dt>gdb_verify</dt> - <dd>Runs the test suite inside of gdb. The test suite is started -  with the flags "<tt>-F -v -v -a</tt>".</dd> - <dt>valgrind_verify</dt> - <dd>Runs the test suite inside of valgrind. The test suite is -  started with the flags "<tt>-F -v -a</tt>".</dd> - <dt>valgrind_just_verify</dt> - <dd>Runs the test suite inside of valgrind, without installing a -  test pike. The test suite is started with the flags "<tt>-F -v -  -a</tt>".</dd> - </dl><p>It is possible to alter the flags given to the -  <tt>test_install</tt> program by using the <tt>TESTARGS</tt> make -  variable.</p><p></p><pre> - make verify TESTARGS="-a -v4 -l2 -t1 -c1 -m" - </pre><p></p> - </dd> - <dt><a name='21.1.1'></a> - <h3 class='header'>21.1.1. The Test Program</h3></dt> - <dd><p>The actual testing is done by the program -  <tt>bin/test_pike.pike</tt>, which can be run as a stand alone -  application to test any Pike binary with any test suite or test -  suites. The Pike binary that executes the test program will be -  tested, and it will be tested with the test suites provided as -  arguments to the test program.</p><p></p><pre> - /home/visbur/Pike/7.2/bin/pike bin/test_pike.pike testsuite1 testsuite2 - </pre><p></p> - <p>The individual testsuite files are generated from testsuite.in files -  scattered about the lib/ and src/ trees. When you run the make targets -  described above, those are made for you automagically, but to do it by hand -  (i e if you added a test to one of them), cd to the top directory and run</p><p></p><pre> - make testsuites - </pre><p></p> - <p>The testsuite files have now appeared in build/<i>arch</i> in -  locations corresponding to where they lived in the pike tree, except -  those from the lib/ hierarchy; those end up in -  build/<i>arch</i>/tlib.</p><p>The test_pike.pike program takes the following attributes.</p><dl> - <dt>-h, --help</dt> - <dd>Displays a help message listing all possible arguments.</dd> - <dt>-a, --auto</dt> - <dd>Let the test program find the testsuits self. It will search for -  files named <tt>testsuite</tt> or <tt>module_testsuite</tt> in the -  current working directory and all subdirectories.</dd> - <dt>--no-watchdog</dt> - <dd>Normally the the test program has a watchdog activated that -  aborts testing if a test takes more than 20 minutes to complete (or -  80 minutes if Pike is compiled with dmalloc). With this argument the -  watchdog will not be used.</dd> - <dt>--watchdog=pid</dt> - <dd>Run only the watchdog and monitor the process with the given pid.</dd> - <dt>-v[level], --verbose[=level]</dt> - <dd>Select the level of verbosity. Every verbose level includes the -  printouts from the levels below. -  <table class='box'> - <tr><td>0</td><td>No extra printouts.</td></tr> - <tr><td>1</td><td>Some additional information printed out after every -  finished block of tests.</td></tr> - <tr><td>2</td><td>Some extra information about test that will or won't be -  run.</td></tr> - <tr><td>3</td><td>Every test is printed out.</td></tr> - <tr><td>4</td><td>Time spent in individual tests are printed out.</td></tr> - <tr><td>10</td><td>The actual pike code compiled, including wrappers, is -  printed. Note that the code will be quoted.</td></tr> - </table> -  -  + <h2 class='header'>21.1. Writing Modules in Pike</h2></dt> + <dd><p> +  Writing modules in pike is by far the easiest way to extend +  pike. They are also useful for structuring a larger programming +  project into different source files. +  </p><p> +  There are two ways of create a pike module written in +  pike. Either create a file named as the module will be called +  with the extension <code class='expr'>.pmod</code> and place all program and +  function definitions in it. The other way, which usually is more +  flexible, is to create a directory named as the module with the +  extension <code class='expr'>.pmod</code> and place all program definitions +  (<code class='expr'>.pike</code>-files) within this directory. If a file called +  <code class='expr'>module.pmod</code> is placed in the directory the function and +  program definitions within it will be merged with the programs +  found in the directory. This file could, as an example, be used +  to specify functions residing in the module, while programs in +  the module are placed in <code class='expr'>.pike</code>-files. +  </p><p> +  Note that Pike modules must not use try to load files relative to +  __FILE__, since such code will break in Microsoft Windows. +  <span class='fixme'>FIXME: Explain why.</span> +  </p></dd> + <dt><a name='21.2'></a> + <h2 class='header'>21.2. Writing Modules in C</h2></dt> + <dd><p><span class='fixme'>FIXME: To be written.</span></p></dd> + <dt><a name='21.2.1'></a> + <h3 class='header'>21.2.1. Practical details</h3></dt> + <dd><p>First of all your module needs a Makefile.in file. It need not be +  more complicated than the following example:   <pre> - $ pike bin/test_pike.pike -v1 testsuite - Doing tests in testsuite (1 tests) - Total tests: 1 (0 tests skipped) - </pre> + # $Id$ + @make_variables@ + VPATH=@srcdir@:@srcdir@/../..:../.. + OBJS= + MODULE_LDFLAGS=@LDFLAGS@ @LIBS@    - <pre> - $ pike bin/test_pike.pike -v2 testsuite - Doing tests in testsuite (1 tests) - Doing test 1 (1 total) at /home/nilsson/Pike/7.3/lib/modules/ADT.pmod/testsuite.in:9 - Failed tests: 0. - Total tests: 1 (0 tests skipped) - </pre> + CONFIG_HEADERS=@CONFIG_HEADERS@    - <pre> - $ pike bin/test_pike.pike -v4 testsuite - Doing tests in testsuite (1 tests) - Doing test 1 (1 total) at /home/nilsson/Pike/7.3/lib/modules/ADT.pmod/testsuite.in:9 -  0: mixed a() { -  1: object s = ADT.Stack(); -  2: s-&gt;push(1); -  3: return s-&gt;pop(); -  4: ; } -  5: mixed b() { return 1; } -  - Time in a(): 0.000, Time in b(): 0.000000 - Failed tests: 0. - Total tests: 1 (0 tests skipped) - </pre> -  - <pre> - $ pike bin/test_pike.pike -v10 testsuite - Doing tests in testsuite (1 tests) - Doing test 1 (1 total) at /home/nilsson/Pike/7.3/lib/modules/ADT.pmod/testsuite.in:9 -  0: mixed a() { -  1: object s = ADT.Stack(); -  2: s-&gt;push(1); -  3: return s-&gt;pop(); -  4: ; } -  5: mixed b() { return 1; } -  -  0: mixed a() { -  1: object s = ADT.Stack(); -  2: s-&gt;push(1); -  3: return s-&gt;pop(); -  4: ; } -  5: mixed b() { return 1; } -  6: int __cpp_line=__LINE__; int __rtl_line=[int]backtrace()[-1][1]; -  7: -  8: int \30306\30271\30310=0; -  9: -  - Time in a(): 0.000, Time in b(): 0.000000 - Failed tests: 0. - Total tests: 1 (0 tests skipped) - </pre> -  </dd> - <dt>-p, --prompt</dt> - <dd>The user will be asked before every test is run.</dd> - <dt>-sX, --start-test=X</dt> - <dd>Where in the testsuite testing should start, e.g. ignores X -  tests in every testsuite.</dd> - <dt>-eX, --end-after=X</dt> - <dd>How many tests should be run.</dd> - <dt>-f, --fail</dt> - <dd>If set, the test program exits on first failure.</dd> - <dt>-F, --fork</dt> - <dd>If set, each testsuite will run in a separate process.</dd> - <dt>-lX, --loop=X</dt> - <dd>The number of times the testsuite should be run. Default is 1.</dd> - <dt>-tX, --trace=X</dt> - <dd>Run tests with trace level X.</dd> - <dt>-c[X], --check[=X]</dt> - <dd>The level of extra pike consistency checks performed. -  <table class='box'> - <tr><td>1</td><td>_verify_internals is run before every test.</td></tr> - <tr><td>2</td><td>_verify_internals is run after every compilation.</td></tr> - <tr><td>3</td><td>_verify_internals is run after every test.</td></tr> - <tr><td>4</td><td>An extra gc and _verify_internals is run before -  every test.</td></tr> - <tr><td>X&lt;0</td><td>For values below zero, _verify_internals will be run -  before every n:th test, where n=abs(X).</td></tr> - </table> -  -  </dd> - <dt>-m, --mem, --memory</dt> - <dd>Prints out memory allocations after the tests.</dd> - <dt>-T, --notty</dt> - <dd>Format output for non-tty.</dd> - <dt>-d, --debug</dt> - <dd>Opens a debug port.</dd> - </dl></dd> - <dt><a name='21.2'></a> - <h2 class='header'>21.2. Writing New Tests</h2></dt> - <dd><p>Whenever you write a new function in a module or in Pike itself -  it is good to add a few test cases in the test suite to ensure that -  regressions are spotted as soon as they appear or to aid in finding -  problems when porting Pike to another platform. Since you have -  written the code, you are the one best suited to come up with tricky -  tests cases. A good test suite for a function includes both some -  trivial tests to ensure that the basic functionality works and some -  nasty tests to test the borderlands of what the function is capable -  of, e.g. empty in parameters.</p><p>Also, when a bug in Pike has been found, a minimized test case -  the triggers the bug should also be added to the test suite. After -  all, this test case has proven to be a useful once.</p></dd> - <dt><a name='21.2.1'></a> - <h3 class='header'>21.2.1. test_any</h3></dt> - <dd><p>The test_any macro tests if the result of two pike expressions -  are similar, e.g. if a==b. Technically the actual test preformed -  is !(a!=b). The first expression should be a complete block, that -  returns a value, while the other expression should be a simple -  pike statement.</p><p></p><pre> - test_any([[ -  int f (int i) {i = 0; return i;}; -  return f (1); - ]],0) - </pre><p></p> - </dd> - <dt><a name='21.2.2'></a> - <h3 class='header'>21.2.2. test_any_equal</h3></dt> - <dd><p>The test_any_equal macro tests if the result of two pike -  expressions are identical, e.g. if equal(a,b). The first -  expression should be a complete block, that returns a value, while -  the other expression should be a simple pike statement.</p><p></p><pre> - test_any_equal([[ -  mixed a=({1,2,3}); -  a[*] += 1; -  return a; - ]], [[ ({2,3,4}) ]]) - </pre><p></p> - </dd> - <dt><a name='21.2.3'></a> - <h3 class='header'>21.2.3. test_eq</h3></dt> - <dd><p>The test_eq macro tests if the result of two pike statements -  are similar, e.g. if a==b. Technicaly the actual test performed is -  !(a!=b).</p><p></p><pre> - test_eq(1e1,10.0); - </pre><p></p> - </dd> - <dt><a name='21.2.4'></a> - <h3 class='header'>21.2.4. test_equal</h3></dt> - <dd><p>The test_equal macro tests if the result of two pike statements -  are identical, e.g. if equal(a,b).</p><p></p><pre> - test_equal([[ ({10,20})[*] + 30 ]], [[ ({40, 50}) ]]) - </pre><p></p> - </dd> - <dt><a name='21.2.5'></a> - <h3 class='header'>21.2.5. test_do</h3></dt> - <dd><p>test_do simply executes its code. This test fails if there is -  any compilation error or if an error is thrown during -  execution.</p><p></p><pre> - test_do([[ -  int x; -  if (time()) -  x = 1; -  else -  foo: break foo; - ]]) - </pre><p></p> - </dd> - <dt><a name='21.2.6'></a> - <h3 class='header'>21.2.6. test_true</h3></dt> - <dd><p>This test succeeds if the pike expression is evaluated into a -  non-zero value.</p><p></p><pre> - test_true([[1.0e-40]]); - </pre><p></p> - </dd> - <dt><a name='21.2.7'></a> - <h3 class='header'>21.2.7. test_false</h3></dt> - <dd><p>This test succeeds if the pike expression is evaluated into a -  zero value.</p><p></p><pre> - test_false(glob("*f","foo")) - </pre><p></p> - </dd> - <dt><a name='21.2.8'></a> - <h3 class='header'>21.2.8. test_compile</h3></dt> - <dd><p>The test_compile macro only tries to compile an expression. It -  fails upon compilarion warnings or errors.</p><p></p><pre> - test_compile([[Stdio.File foo=Stdio.File();]]) - </pre><p></p> - </dd> - <dt><a name='21.2.9'></a> - <h3 class='header'>21.2.9. test_compile_any</h3></dt> - <dd><p>Tests if the code compiles, just as <tt>test_compile</tt>, but -  is a complete block of code and not just an expression.</p><p></p><pre> - test_compile_any([[ -  void foo() -  { -  Stdio.File bar(int x, int y) -  { -  return 0; -  }; -  } - ]]) - </pre><p></p> - </dd> - <dt><a name='21.2.10'></a> - <h3 class='header'>21.2.10. test_compile_error</h3></dt> - <dd><p>Does the inverse of <tt>test_compile</tt>; verifies that the -  code does not compile.</p><p></p><pre> - test_compile_error([[ int a="a"; ]]) - </pre><p></p> - </dd> - <dt><a name='21.2.11'></a> - <h3 class='header'>21.2.11. test_compile_error_any</h3></dt> - <dd><p>Does the inverse of <tt>test_compile_any</tt>; verifies that -  the code does not compile.</p><p></p><pre> - test_compile_error_any([[ -  int a=5; -  string b="a"; -  a=b; - ]]) - </pre><p></p> - </dd> - <dt><a name='21.2.12'></a> - <h3 class='header'>21.2.12. test_compile_warning</h3></dt> + @dynamic_module_makefile@ + @dependencies@ + </pre></p><p>A few customizations must however be done. The <tt>OBJS</tt> variable should +  contain all the object files produced in your module. You should +  add to the <tt>MODULE_LDFLAGS</tt> variable all the needed <tt>-L&lt;libdir&gt; -R&lt;libdir&gt;</tt> +  options followed by all the needed <tt>-l&lt;lib&gt;</tt> options. If you want your +  module to always be linked statically, change <tt>@dynamic_module_makefile@</tt> +  to <tt>@static_module_makefile@</tt>. Normally you do not need to manually add +  any dependencies to Makefile.in.</p><p>There must be a testsuite.in file in the modules directory, even if it +  only is an empty file.</p><p>You should have a configure.in file for your module and it should test +  for all features that you need. Do not trust the global configure tests +  to do thing for you. Further, your configure.in should contain the line +  <tt>sinclude(../module_configuration.in)</tt>.</p><p>All C/C++ files should include <tt>"global.h"</tt> as the first included file. It +  is also good if they contain <tt>RCSID($Id$)</tt>.</p><p>When building your module for the first time you need to: +  <ol> + </ol></p></dd> + <dt><a name='21.3'></a> + <h2 class='header'>21.3. Special Module Variables and functions</h2></dt>   <dd></dd> - <dt><a name='21.2.13'></a> - <h3 class='header'>21.2.13. test_eval_error</h3></dt> - <dd></dd> - <dt><a name='21.2.14'></a> - <h3 class='header'>21.2.14. test_define_program</h3></dt> - <dd></dd> - <dt><a name='21.2.15'></a> - <h3 class='header'>21.2.15. test_program</h3></dt> - <dd></dd> - <dt><a name='21.2.16'></a> - <h3 class='header'>21.2.16. cond</h3></dt> - <dd></dd> - <dt><a name='21.2.17'></a> - <h3 class='header'>21.2.17. ifefun</h3></dt> - <dd></dd> - <dt><a name='21.2.18'></a> - <h3 class='header'>21.2.18. nonregression</h3></dt> - <dd></dd></dl></body></html> + <dt><a name='21.3.1'></a> + <h3 class='header'>21.3.1. _module_value</h3></dt> + <dd><p> +  If <code class='expr'>_module_value</code> is non-zero it will be used as +  the value of the module. <code class='expr'>_module_value</code> has to be of +  a type which is indicable, ie. an object, mapping or +  multiset. +  </p></dd> + <dt><a name='21.3.2'></a> + <h3 class='header'>21.3.2. The indexing operator</h3></dt> + <dd><p> +  If a <code>lfun::`[]</code> is defined in a module it will be +  called when the module is indexed using the .-operator. +  </p></dd></dl></body></html>