Develop:Tests

From FreeNATS Wiki

Jump to: navigation, search

Contents

Developing Tests

Developing FreeNATS server-side PHP tests is quite easy. They consist of a PHP file defining a class containing one or more member functions.

You may also like to see the developing with FreeNATS documentation for some globally available features and information.

Example Test

To demonstrate how this is done we shall work through an example. We want to create a test that opens a web page and checks if it contains the text "online". The page we want to check is http://someserver/.

First we create a PHP file in the server/base/site/tests directory called something meaningful like pagetest.php (it must have a PHP extension and you must also have set the system variable site.include.tests to 1 which will cause FreeNATS to include all .php files in the server/site/tests directory on startup).

To keep the example as clean as possible the actual test is done by an external function check_page_text($url,$text) which returns true if the text is found and false if it isn't.

Example 1: Simple Test

  1. <?php
  2. function check_page_text($url,$text)
  3. {
  4. $fp=fopen($url,"r"); // open the URL
  5. if ($fp<=0) return false; // fail if can't open
  6. $body="";
  7. while (!feof($fp))
  8. $body.=fgets($fp,1024); // read into the body in 1k chunks
  9. fclose($fp); // finished with pointer
  10. if (strpos($body,$text)===false) return false; // not found
  11. return true; // found
  12. }
  13.  
  14. // Ok that was the actual text-check function now the actual integration within FreeNATS
  15. global $NATS; // make sure we have the NATS object
  16. // n.b. You may like to encase this in a ifset($NATS) block so you can build/test
  17. // without having to be within the NATS environment.
  18.  
  19. class Pagecheck_Test extends FreeNATS_Local_Test // create a new class extending FreeNATS_Local_Test
  20. {
  21.  
  22. function DoTest($testname,$param,$hostname,$timeout,$params) // do the actual test (REQUIRED)
  23. {
  24. if (check_page_text("http://someserver/","online")==true) return 1;
  25. return 0;
  26. }
  27.  
  28. function Evaluate($result) // be able to evaluate our result (REQUIRED)
  29. {
  30. if ($result>0) return 0; // FreeNATS passed (0) flag
  31. return 2; // FreeNATS failed (2) flag
  32. }
  33. }
  34.  
  35. // Now we have defined the class we must register it with FreeNATS
  36.  
  37. $params=array(); // blank parameters array (see later for more detail)
  38.  
  39. $NATS->Tests->Register(
  40. "pagecheck", // the internal simple test name (must not conflict with anything else)
  41. "Pagecheck_Test", // the class name (above)
  42. $params, // parameters (blank for now)
  43. "Page Online Checker", // the display name of the test in the interface
  44. 1, // the revision number of the test
  45. "Our Page Checker"); // extended description for the test module used in overview
  46.  
  47. ?>

And there you have it. In the simple example above the test will now appear to be added to a node. Recorded data (and last value) will be 0 for no matching text or 1 for a match and the evaluate function will show this as passed or failed.

Adding Parameters (Simply)

Parameters for your test can be simply offered to the user by defining them in the $params array. For each defined parameter the user interface will show the title given and a text input box. Whatever the user inputs and saves is then provided to the DoTest function in the param variable (the first parameter) and in params[0-9] ($params[0] is equal to $param).

To add the ability for the user to configure the remote URL and string to search for you can modify the code as follows:

Example 2. Adding Simple Parameters

  1. class Pagecheck_Test extends FreeNATS_Local_Test // create a new class extending FreeNATS_Local_Test
  2. {
  3.  
  4. function DoTest($testname,$param,$hostname,$timeout,$params) // do the actual test (REQUIRED)
  5. {
  6. if (check_page_text($params[0],$params[1])==true) return 1; // use parameters 0 and 1
  7. return 0;
  8. }
  9.  
  10. function Evaluate($result) // be able to evaluate our result (REQUIRED)
  11. {
  12. if ($result>0) return 0; // FreeNATS passed (0) flag
  13. return 2; // FreeNATS failed (2) flag
  14. }
  15. }
  16.  
  17. // Now we have defined the class we must register it with FreeNATS
  18.  
  19. $params=array(
  20. "URL/Full http qualified URL", // note the / use - text after it is displayed under the field in italics
  21. "Search String");
  22.  
  23. $NATS->Tests->Register(
  24. "pagecheck", // the internal simple test name (must not conflict with anything else)
  25. "Pagecheck_Test", // the class name (above)
  26. $params, // parameters (no longer blank)
  27. "Page Online Checker", // the display name of the test in the interface
  28. 1, // the revision number of the test
  29. "Our Page Checker"); // extended description for the test module used in overview

In the code above we have specified two parameters. These are the titles that will be displayed in the test edit dialogue. The URL title has a /. If a title contains a / the text after it will be displayed in italics under the field name.

In this example the output would roughly resemble:

    URL: INPUT_BOX
    Full http qualified URL
    Search String: INPUT_BOX

Adding More Complex Parameters

If you need to have better control over the parameters you can implement a DisplayForm method in your class which returns a string containing the parameter options. This is output as part of the test edit dialogue which takes a reference to the test data array. This can then be used to create/populate your custom field types.

The variable array is the row record from the fnlocaltest table for this specific test and as such has available testparam and testparam1-9 as indexes.

Lets say we want to update our example to include URL-based authentication. We don't want the user to have to specify it manually in the URL. We could just add two new parameters to the array but we want to be clever and not display the password every time. We want to change it only if the user inputs something new (and of course have a checkbox to clear it as the user can't input nothing in this case).

Any change to the actual test function isn't shown here as that is not the point of this documentation!

Example 3. Adding More Complex Parameters

  1. class Pagecheck_Test extends FreeNATS_Local_Test // create a new class extending FreeNATS_Local_Test
  2. {
  3.  
  4. function DoTest($testname,$param,$hostname,$timeout,$params) // do the actual test (REQUIRED)
  5. {
  6. if (check_page_text($params[0],$params[1],$params[2],$params[3])==true) return 1; // use parameters 0 and 1
  7. return 0;
  8. }
  9.  
  10. function Evaluate($result) // be able to evaluate our result (REQUIRED)
  11. {
  12. if ($result>0) return 0; // FreeNATS passed (0) flag
  13. return 2; // FreeNATS failed (2) flag
  14. }
  15.  
  16. function DisplayForm(&$test) // note the reference & is used
  17. {
  18. $out=""; // output buffer
  19. $out.="<table width=100% border=0>";
  20. $out.="<tr><td align=right>URL :</td>";
  21. $out.="<td align=left>";
  22. $out.="<input type=text size=30 name=testparam value=\"".$test['testparam']."\">";
  23. $out.="<br><i>Fully-qualified URL including http://</i>";
  24. $out.="</td></tr>";
  25. $out.="<tr><td align=right>String :</td>";
  26. $out.="<td align=left>";
  27. $out.="<input type=text size=30 name=testparam1 value=\"".$test['testparam1']."\">";
  28. $out.="<br><i>String to search for</i>";
  29. $out.="</td></tr>";
  30.  
  31. // Now we have pretty-much replicated what was done with the old params array
  32.  
  33. $out.="<tr><td align=right>Username :</td>";
  34. $out.="<td align=left>";
  35. $out.="<input type=text size=30 name=testparam2 value=\"".$test['testparam2']."\">";
  36. $out.="<br><i>Specify to use HTTP-AUTH on the URL</i>";
  37. $out.="</td></tr>";
  38.  
  39. // so far so much the same... but...
  40. $out.="<tr><td align=right>Password :</td>";
  41. $out.="<td align=left>";
  42. $out.="<input type=text size=30 name=testparam3 value=\"\">"; // dont display it
  43. $out.="<input type=hidden name=keepparam3 value=1>"; // don't update testparam3 (if blank)
  44. $out.="<br><i>Enter a new password to set or... ";
  45. $out.="<input type=checkbox name=clearparam3 value=1> "; // clears testparam3 if set
  46. $out.="clear it</i>";
  47. $out.="</td></tr>";
  48. echo $out; // output the buffer
  49. }
  50. }
  51.  
  52. // Now we have defined the class we must register it with FreeNATS
  53.  
  54. $params=array(); // a blank array now
  55.  
  56. $NATS->Tests->Register(
  57. "pagecheck", // the internal simple test name (must not conflict with anything else)
  58. "Pagecheck_Test", // the class name (above)
  59. $params, // parameters (blank for now)
  60. "Page Online Checker", // the display name of the test in the interface
  61. 1, // the revision number of the test
  62. "Our Page Checker"); // extended description for the test module used in overview

Securing API/View Output

Although all test accounts used in FreeNATS shouldn't be live or production-sensitive let's say we were really worried about the test data getting into the wrong hands when we request it as a JavaScript array for a view or data API call.

We can optionally implement a ProtectOutput function that takes a reference to the data array about to be output and modifies it as you wish. In this example we want to protect testparam3 which holds the HTTP-AUTH password if specified.

Example 4. Protecting API Output

  1. class Pagecheck_Test extends FreeNATS_Local_Test // create a new class extending FreeNATS_Local_Test
  2. {
  3.  
  4. function DoTest($testname,$param,$hostname,$timeout,$params) // do the actual test (REQUIRED)
  5. {
  6. if (check_page_text($params[0],$params[1],$params[2],$params[3])==true) return 1; // use parameters 0 and 1
  7. return 0;
  8. }
  9.  
  10. function Evaluate($result) // be able to evaluate our result (REQUIRED)
  11. {
  12. if ($result>0) return 0; // FreeNATS passed (0) flag
  13. return 2; // FreeNATS failed (2) flag
  14. }
  15.  
  16. function ProtectOutput(&$test) // note the reference
  17. {
  18. $test['testparam3']=""; // blank it for output
  19. return true;
  20. }

Timing the Test

We can time the test through the use of a TFNTimer object. If possible tests should have their DNS pre-cached (or ideally pre-resolved and use the IP for testing) either by your own method or using the url_lookup() (for a FQDN URL) or ip_lookup() (for a hostname) globally available functions.

The TFNTimer object is simple enough as can be seen the example below. It will return a "safe" time i.e. always rounded to 4d.p. (ms accuracy) and a minumum of 0.0001 (which may not be strictly true if the time taken was 0.00001 or a "time shift" event such as NTP sync happened during the test execution).

We now change the test function to return a negative number on failure and the elapsed time on success. We don't need to update our Evaluate() function is it already returns passed for a result > 0 and failure for anything else.

Please note in the code below only the timer-specific new code is highlighted. The "new" URL HTTP-AUTH code is not as although not seen before it is not specific to this documentation.

Example 5. Timing the Test

  1. <?php
  2. function check_page_text($url,$text,$user="",$pass="")
  3. {
  4. $timer=new TFNTimer(); // initialise the timer
  5. url_lookup($url); // pre-resolve the DNS into cache
  6.  
  7. if ($user!="") // use HTTP-AUTH
  8. {
  9. $pos=strpos($url,"://");
  10. if ($pos===false) return -1; // not a valid URL
  11. $protocol=substr($url,0,$pos+3); // protocol section
  12. $uri=substr($url,$pos+3); // uri section
  13. $url=$protocol.$user.":".$pass."@".$uri; // make http://user:pass@uri
  14. }
  15. $timer->Start(); // start the timer
  16. $fp=fopen($url,"r"); // open the URL
  17. if ($fp<=0) return false; // fail if can't open
  18. // or we could start it here to not include opening times...
  19. $body="";
  20. while (!feof($fp))
  21. $body.=fgets($fp,1024); // read into the body in 1k chunks
  22. $elapsed=$timer->Stop(); // get the elapsed time at this point
  23. fclose($fp); // finished with pointer
  24. if (strpos($body,$text)===false) return -1; // not found
  25. return $elapsed; // return a positive elapsed time on success
  26. }


Test Units

This is not shown in any of the actual code samples as it was implemented later

You can assign units in short and long form to your test after it has been registered with something like:

$NATS->Tests->Register("sometest","someclass",$params,"Some Tester",1,"Some Tester We Wrote");
$NATS->Tests->SetUnits("sometest","Seconds","s"); // long format first


Finished Total Example

Example 6: Finished Example

  1. <?php
  2. function check_page_text($url,$text,$user="",$pass="") // our actual test function
  3. {
  4. $timer=new TFNTimer(); // initialise the timer
  5. url_lookup($url); // pre-resolve the DNS into cache
  6.  
  7. if ($user!="") // use HTTP-AUTH
  8. {
  9. $pos=strpos($url,"://");
  10. if ($pos===false) return -1; // not a valid URL
  11. $protocol=substr($url,0,$pos+3); // protocol section
  12. $uri=substr($url,$pos+3); // uri section
  13. $url=$protocol.$user.":".$pass."@".$uri; // make http://user:pass@uri
  14. }
  15. $timer->Start(); // start the timer
  16. $fp=fopen($url,"r"); // open the URL
  17. if ($fp<=0) return false; // fail if can't open
  18. // or we could start it here to not include opening times...
  19. $body="";
  20. while (!feof($fp))
  21. $body.=fgets($fp,1024); // read into the body in 1k chunks
  22. $elapsed=$timer->Stop(); // get the elapsed time at this point
  23. fclose($fp); // finished with pointer
  24. if (strpos($body,$text)===false) return -1; // not found
  25. return $elapsed; // return a positive elapsed time on success
  26. }
  27.  
  28. // Ok that was the actual text-check function now the actual integration within FreeNATS
  29. global $NATS;
  30. // n.b. You may like to encase this in a ifset($NATS) block so you can build/test
  31. // without having to be within the NATS environment.
  32.  
  33. class Pagecheck_Test extends FreeNATS_Local_Test // create a new class extending FreeNATS_Local_Test
  34. {
  35.  
  36. function DoTest($testname,$param,$hostname,$timeout,$params) // do the actual test (REQUIRED)
  37. {
  38. if (check_page_text($params[0],$params[1],$params[2],$params[3])==true) return 1;
  39. return 0;
  40. }
  41.  
  42. function Evaluate($result) // be able to evaluate our result (REQUIRED)
  43. {
  44. if ($result>0) return 0; // FreeNATS passed (0) flag
  45. return 2; // FreeNATS failed (2) flag
  46. }
  47.  
  48. function ProtectOutput(&$test) // output protections (optional)
  49. {
  50. $test['testparam3']=""; // blank it for output
  51. return true;
  52. }
  53.  
  54. function DisplayForm(&$test) // nice user form (optional)
  55. {
  56. $out=""; // output buffer
  57. $out.="<table width=100% border=0>";
  58. $out.="<tr><td align=right>URL :</td>";
  59. $out.="<td align=left>";
  60. $out.="<input type=text size=30 name=testparam value=\"".$test['testparam']."\">";
  61. $out.="<br><i>Fully-qualified URL including http://</i>";
  62. $out.="</td></tr>";
  63. $out.="<tr><td align=right>String :</td>";
  64. $out.="<td align=left>";
  65. $out.="<input type=text size=30 name=testparam1 value=\"".$test['testparam1']."\">";
  66. $out.="<br><i>String to search for</i>";
  67. $out.="</td></tr>";
  68.  
  69. // Now we have pretty-much replicated what was done with the old params array
  70.  
  71. $out.="<tr><td align=right>Username :</td>";
  72. $out.="<td align=left>";
  73. $out.="<input type=text size=30 name=testparam2 value=\"".$test['testparam2']."\">";
  74. $out.="<br><i>Specify to use HTTP-AUTH on the URL</i>";
  75. $out.="</td></tr>";
  76.  
  77. // so far so much the same... but...
  78. $out.="<tr><td align=right>Password :</td>";
  79. $out.="<td align=left>";
  80. $out.="<input type=text size=30 name=testparam3 value=\"\">"; // dont display it
  81. $out.="<input type=hidden name=keepparam3 value=1>"; // don't update testparam3 (if blank)
  82. $out.="<br><i>Enter a new password to set or... ";
  83. $out.="<input type=checkbox name=clearparam3 value=1> "; // clears testparam3 if set
  84. $out.="clear it</i>";
  85. $out.="</td></tr>";
  86. echo $out; // output the buffer
  87. }