home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / UTILS / WEBLINT / WEBLINT.ZIP / weblint / test.pl < prev    next >
Encoding:
Perl Script  |  1996-02-12  |  26.4 KB  |  848 lines

  1. : # use perl
  2.         eval 'exec perl -S $0 "$@"'
  3.                 if $runnning_under_some_shell;
  4.  
  5. #
  6. # test.pl - regression tests for weblint
  7. #
  8. # Copyright (C) 1995,1996 Neil Bowers.  All rights reserved.
  9. #
  10. # See README for additional blurb.
  11. # Bugs, comments, suggestions welcome: neilb@khoral.com
  12. #
  13. $VERSION    = '1.007';
  14. ($PROGRAM = $0) =~ s@.*/@@;
  15. $FILENAME    = 'testfile.html';
  16. $LOGFILE    = 'weblint-test.log';
  17. $ENV{WEBLINTRC} = '/dev/null';
  18. @TMPDIR_OPTIONS    = ('/usr/tmp', '/tmp', '/var/tmp');
  19.  
  20.  
  21. &WeblintTestInitialize();
  22.  
  23.  
  24. &ExpectOK('simple syntactically correct html', '',
  25.       "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  26.       "<BODY>this is the body</BODY>\n</HTML>");
  27.  
  28. &ExpectOK('paragraph usage', '',
  29.       "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  30.           "<BODY>first paragraph<P>second paragraph</BODY>\n</HTML>");
  31.  
  32. &ExpectOK('html which starts with DOCTYPE specifier', '',
  33.       "<!DOCTYPE HTML PUBLIC '-//W3O//DTD WWW HTML 2.0//EN'>\n".
  34.       "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  35.       "<BODY>this is the body</BODY>\n</HTML>");
  36.  
  37. &ExpectOK('acceptable usage of META element', '',
  38.       '<HTML><HEAD><TITLE>foo</TITLE>'.
  39.       '<META NAME="IndexType" CONTENT="Service"></HEAD>'.
  40.       '<BODY>this is the body</BODY></HTML>');
  41.  
  42. &ExpectOK('correct use of information type and font style elements', '',
  43.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  44.       "<EM>Emphasized Text</EM>\n".
  45.       "<CITE>Cited Text</CITE>\n".
  46.       "<STRONG>Strongly emphasized Text</STRONG>\n".
  47.       "<CODE>Teletype Text</CODE>\n".
  48.       "<SAMP>sequence of literal characters</SAMP>\n".
  49.       "<KBD>Keyboarded Text</KBD>\n".
  50.       "<VAR>Variable name</VAR>\n".
  51.       "<DFN>Defining instance</DFN>\n".
  52.       "<Q>Short quotation</Q>\n".
  53.       "<LANG>alter language context</LANG>\n".
  54.       "<AU>Name of author</AU>\n".
  55.       "<PERSON>name of a person</PERSON>\n".
  56.       "<ACRONYM>acronym</ACRONYM>\n".
  57.       "<ABBREV>Abbreviation</ABBREV>\n".
  58.       "<INS>Inserted text</INS>\n".
  59.       "<DEL>Deleted text</DEL>\n".
  60.       "<B>Bold text</B>\n".
  61.       "<I>Italic text</I>\n".
  62.       "<TT>Teletype text</TT>\n".
  63.       "<U>Underlined text</U>\n".
  64.       "<S>Striked through text</S>\n".
  65.       "<BIG>Big text</BIG>\n".
  66.       "<SMALL>Small text</SMALL>\n".
  67.       "<SUB>Subscript text</SUB>\n".
  68.       "<SUP>Superscript text</SUP>\n".
  69.       '</BODY></HTML>');
  70.  
  71. &ExpectOK('IMG element with ALT and ISMAP attributes', '',
  72.       '<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>'.
  73.       '<IMG SRC=foo.gif ISMAP ALT="alt text">'.
  74.       '</BODY></HTML>');
  75.  
  76. &ExpectOK('newline within a tag', '',
  77.       '<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>'.
  78.       '<IMG SRC="foo.gif"'."\n".'ALT="alt text">'.
  79.       '</BODY></HTML>');
  80.  
  81. &ExpectOK('simple comment', '',
  82.       "<!-- comment before the HTML element -->\n".
  83.       "<HTML>\n".
  84.       "<!-- comment between the HTML and HEAD elements -->\n".
  85.       "<HEAD>\n".
  86.       "<!-- comment in the HEAD element -->\n".
  87.       "<TITLE>foo</TITLE></HEAD><BODY>".
  88.       "<!-- this is a simple comment in the body -->\n".
  89.       "this is the body\n".
  90.       "</BODY>\n".
  91.       "<!-- comment between end of BODY and end of HTML -->\n".
  92.       "</HTML>\n".
  93.       "<!-- comment after the end of the HTML element -->\n");
  94.  
  95. &ExpectOK('comment with space before the closing >', '',
  96.       '<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>'.
  97.       '<!-- this is a simple comment -- >'.
  98.       'this is the body'.
  99.       '</BODY></HTML>');
  100.  
  101. &ExpectOK('whitespace around the = of an element attribute', '',
  102.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>".
  103.       "<IMG SRC = foo.gif ALT=\"alt text\">".
  104.       "</BODY></HTML>");
  105.  
  106. &ExpectOK('legal unordered list', '',
  107.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  108.       "<UL>\n".
  109.       "<LI>first item\n".
  110.       "<LI>second item</LI>\n".
  111.       "</UL>\n".
  112.       "</BODY></HTML>\n");
  113.  
  114. &ExpectOK('legal definition list', '',
  115.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  116.       "<DL>\n".
  117.       "<DT>first tag<DD>first definition\n".
  118.       "<DT>second tag<DD>second definition\n".
  119.       "</DL>\n".
  120.       "</BODY></HTML>\n");
  121.  
  122. &ExpectOK('simple table', '',
  123.       '<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>'.
  124.       '<TABLE><TR><TH>height<TD>1.0<TR><TH>weight<TD>1.0</TABLE>'.
  125.       '</BODY></HTML>');
  126.  
  127. &ExpectWARN('table without TR', '',
  128.         "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  129.         "<TABLE><TH>height<TD>1.0<TR><TH>weight<TD>1.0</TABLE>".
  130.         "</BODY></HTML>",
  131.         2, 'required-context',
  132.         2, 'required-context');
  133.  
  134. &ExpectOK('simple figure with caption', '',
  135.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  136.       "<FIG SRC=\"nicodamus.jpeg\">\n".
  137.           "<CAPTION>Ground dweller: <I>Nicodamus bicolor</I>\n".
  138.       "builds silk snares</CAPTION>\n".
  139.       "<P>A small hairy spider light fleshy red in color with a brown ".
  140.       "abdomen.\n<CREDIT>J. A. L. Cooke/OSF</CREDIT>\n".
  141.       "</FIG></BODY></HTML>");
  142.  
  143. &ExpectOK('simple math usage', '',
  144.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  145.       "<MATH>\n".
  146.       "<BOX>1+x<OVER>sin x</BOX>\n".
  147.       "<ABOVE>1+x</ABOVE>\n".
  148.       "<BELOW>1+x</BELOW>\n".
  149.       "<SQRT>1+x</SQRT>\n".
  150.       "<ROOT>3<OF>1+x</ROOT>\n".
  151.       "<ARRAY><ROW><ITEM>a<SUB>11</SUB><ITEM>a<SUB>12</SUB></ARRAY>\n".
  152.       "</MATH>\n".
  153.       "</BODY></HTML>\n");
  154.  
  155. &ExpectWARN('no HTML tags around document', '',
  156.         "<HEAD><TITLE>title</TITLE></HEAD>\n".
  157.         "<BODY>this is the body</BODY>\n",
  158.         1, 'html-outer',
  159.         1, 'must-follow');
  160.  
  161. &ExpectWARN('whitespace between opening < and tag name', '',
  162.         "<HTML><HEAD>< TITLE>title</TITLE></HEAD>\n".
  163.         "<BODY>this is the body</BODY></HTML>",
  164.         1, 'leading-whitespace');
  165.  
  166. &ExpectWARN('no TITLE element in HEAD', '',
  167.         "<HTML>\n<HEAD></HEAD>\n<BODY>this is the body</BODY>\n</HTML>",
  168.         2, 'empty-container',
  169.         2, 'require-head');
  170.  
  171. &ExpectWARN('unclosed TITLE in HEAD', '',
  172.         "<HTML>\n<HEAD><TITLE></HEAD>\n".
  173.         "<BODY>this is the body</BODY>\n</HTML>",
  174.         2, 'unclosed-element');
  175.  
  176. &ExpectWARN('bad style to use "here" as anchor text', '',
  177.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  178.         "<BODY><A HREF=\"foo.html\">here</A></BODY>\n</HTML>",
  179.         3, 'here-anchor');
  180.  
  181. &ExpectWARN('mis-matched heading tags <H1> .. </H2>', '',
  182.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  183.         "<BODY><H1>title</H2></BODY>\n</HTML>",
  184.         3, 'heading-mismatch');
  185.  
  186. &ExpectWARN('obsolete element', '',
  187.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  188.         "<BODY><XMP>foobar()</XMP></BODY></HTML>",
  189.         3, 'obsolete');
  190.  
  191. &ExpectWARN('illegal attribute in B element', '',
  192.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  193.         "<BODY><B FOO>foobar</B></BODY></HTML>",
  194.         3, 'unknown-attribute');
  195.  
  196. &ExpectWARN('empty tag: <>', '',
  197.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  198.         "<BODY><>this is the body</BODY></HTML>",
  199.         3, 'unknown-element');
  200.  
  201. &ExpectWARN('netscape tags *without* netscape enabled', '',
  202.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  203.         "<BODY BGCOLOR=\"#ffffff\">\n".
  204.         "<CENTER>centered text</CENTER>\n".
  205.         "<BLINK>blinking text</BLINK>\n".
  206.         "<FONT SIZE=+1>larger font size text</FONT>\n".
  207.         "</BODY></HTML>",
  208.         3, 'netscape-attribute',    # BGCOLOR attribute for BODY
  209.         4, 'netscape-markup',    # one for the opening tag of CENTER
  210.         4, 'netscape-markup',    # one for the closing tag of CENTER
  211.         5, 'netscape-markup',
  212.         5, 'netscape-markup',
  213.         6, 'netscape-markup',
  214.         6, 'attribute-format',    # hmm, checking tags of unknown elts?
  215.         6, 'netscape-markup');
  216.  
  217. &ExpectOK('netscape tags *with* netscape enabled', '-x netscape',
  218.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  219.         "<BODY BGCOLOR=\"#ffffff\">\n".
  220.         "<CENTER>centered text</CENTER>\n".
  221.         "<BLINK>blinking text</BLINK>\n".
  222.         "<FONT SIZE=+1>larger font size text</FONT>\n".
  223.         "</BODY></HTML>");
  224.  
  225. &ExpectWARN('not allowed to nest FORM elements', '',
  226.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  227.         "<BODY>\n".
  228.         "<FORM METHOD=post ACTION=\"http://www.khoral.com/foo\">\n".
  229.         "<FORM METHOD=post ACTION=\"http://www.khoral.com/foo\">\n".
  230.         "This is inside the nested form".
  231.         "</FORM>\n".
  232.         "</FORM></BODY></HTML>",
  233.         5, 'nested-element');
  234.  
  235. &ExpectWARN('CAPTION element appearing outside of TABLE or FIG', '',
  236.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  237.         "<BODY>\n".
  238.         "<TABLE><CAPTION>legal use of caption</CAPTION></TABLE>\n".
  239.         "<FIG><CAPTION>legal use of caption</CAPTION></FIG>\n".
  240.         "<CAPTION>this is an invalid use of caption</CAPTION>\n".
  241.         "</BODY></HTML>",
  242.         5, 'required-context');
  243.  
  244. &ExpectWARN('LH element must be used in UL, OL or DL', '',
  245.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  246.         "<BODY>\n".
  247.         "<UL><LH>unordered list heading</LH></UL>\n".
  248.         "<OL><LH>ordered list heading</LH></OL>\n".
  249.         "<DL><LH>definition list heading</LH></DL>\n".
  250.         "<LH>illegal use of list heading</LH>\n".
  251.         "</BODY></HTML>",
  252.         6, 'required-context',
  253.         6, 'must-follow');
  254.  
  255. &ExpectWARN('LI element must be used in DIR, MENU, OL, OL or UL', '',
  256.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  257.         "<BODY>\n".
  258.         "<DIR><LI>legal list item in DIR</DIR>\n".
  259.         "<MENU><LI>legal list item in MENU</MENU>\n".
  260.         "<OL><LI>legal list item in OL</OL>\n".
  261.         "<UL><LI>legal list item in UL</UL>\n".
  262.         "<LI>illegal list item\n".
  263.         "</BODY></HTML>",
  264.         7, 'required-context');
  265.  
  266. &ExpectWARN('unclosed comment', '',
  267.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  268.         "<BODY>\n".
  269.         "<!-- this is an unclosed comment >\n".
  270.         "</BODY></HTML>",
  271.         3, 'unclosed-comment');
  272.  
  273. &ExpectWARN('use of physical font markup', '-e physical-font',
  274.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  275.         "<BODY>\n".
  276.         "<B>This is bold text</B>\n".
  277.         "<STRONG>This is strong text</STRONG>\n".
  278.         "</BODY></HTML>",
  279.         3, 'physical-font');
  280.  
  281. &ExpectWARN('repeated attribute', '',
  282.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  283.         "<BODY>\n".
  284.         "<IMG SRC=\"foo.gif\" SRC=\"foo.gif\" ALT=\"alt text\">\n".
  285.         "</BODY></HTML>",
  286.         3, 'repeated-attribute');
  287.  
  288. &ExpectWARN('no HTML tags around document, last thing is valid comment', '',
  289.         "<HEAD><TITLE>title</TITLE></HEAD>\n".
  290.         "<BODY>this is the body</BODY>\n".
  291.         "<!-- this is a valid comment -->\n",
  292.         1, 'html-outer',
  293.         1, 'must-follow');
  294.  
  295. &ExpectWARN('spurious text between HEAD and BODY elements', '',
  296.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  297.         "Should not put any text here!\n".
  298.         "<BODY>this is the body</BODY></HTML>\n",
  299.         3, 'must-follow');
  300.  
  301. &ExpectWARN('list heading appears after first list element', '',
  302.         "<HTML><HEAD><TITLE>title</TITLE></HEAD><BODY>\n".
  303.         "<UL>\n".
  304.         "<LI>text of first list item</LI>\n".
  305.         "<LH>this is the list heading</LH>\n".
  306.         "</UL>\n".
  307.         "</BODY></HTML>\n",
  308.         4, 'must-follow');
  309.  
  310. &ExpectWARN('empty title element', '',
  311.         "<HTML><HEAD><TITLE></TITLE></HEAD>\n".
  312.         "<BODY>this is the body</BODY></HTML>\n",
  313.         1, 'empty-container');
  314.  
  315. &ExpectWARN('empty list element', '',
  316.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  317.         "<BODY>\n".
  318.         "<UL>\n".
  319.         "<LI>this is the first element\n".
  320.         "<LI>\n".
  321.         "<LI>this is the third or second element...\n".
  322.         "</UL>\n".
  323.         "</BODY></HTML>",
  324.         5, 'empty-container');
  325.  
  326. &ExpectWARN('attributes on closing tag', '',
  327.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  328.         "<BODY>\n".
  329.         "<A NAME=\"foobar\">bleh</A NAME=\"foobar\">\n".
  330.         "</BODY></HTML>\n",
  331.         3, 'closing-attribute');
  332.  
  333. &ExpectWARN('use of netscape attributes without netscape extension', '',
  334.         "<HTML><HEAD><TITLE>title</TITLE></HEAD>\n".
  335.         "<BODY BGCOLOR=\"#fefefe\">\n".
  336.         "Nothing exciting in the body\n".
  337.         "</BODY></HTML>\n",
  338.         2, 'netscape-attribute');
  339.  
  340. &ExpectWARN("use of ' as attribute value delimiter", '',
  341.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  342.       "<IMG SRC = foo.gif ALT='alt text'>\n".
  343.       "</BODY></HTML>\n",
  344.       2, 'attribute-delimiter');
  345.  
  346. &ExpectWARN("IMG without HEIGHT and WIDTH attributes", '-e img-size',
  347.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  348.       "<IMG SRC = foo.gif ALT=\"alt text\">\n".
  349.       "</BODY></HTML>\n",
  350.       2, 'img-size');
  351.  
  352. &ExpectOK('non-empty container, with comment last thing', '',
  353.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  354.         "<BODY>\n".
  355.         "<PRE>\n".
  356.         "Some text ...\n".
  357.         "<!-- last thing in container is a valid comment -->\n".
  358.         "</PRE>\n".
  359.         "</BODY></HTML>");
  360.  
  361. &ExpectWARN('use of -pedantic command-line switch', '-pedantic',
  362.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  363.       "<IMG SRC = foo.gif ALT=\"alt text\">\n".
  364.       "<B>This is bold text -- should use the STRONG element</B>\n".
  365.       "<A HREF=\"foobar.html\">non-existent file</A>\n".
  366.       "</BODY></HTML>\n",
  367.       1, 'mailto-link',
  368.       2, 'img-size',
  369.       3, 'physical-font');
  370.  
  371. &ExpectWARN('leading whitespace in container', '-e container-whitespace',
  372.       "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  373.       "<A HREF=foobar.html> hello</A>\n".
  374.       "</BODY></HTML>\n",
  375.       2, 'container-whitespace');
  376.  
  377. &ExpectOK('valid Java applet', '-x java',
  378.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  379.         "<BODY>\n".
  380.         "<APPLET CODEBASE=\"http://java.sun.com/JDK-prebeta1/applets/NervousText\" CODE=\"NervousText.class\" WIDTH=400 HEIGHT=75 ALIGN=CENTER>\n".
  381.         "<PARAM NAME=\"text\" VALUE=\"This is the applet viewer.\">\n".
  382.         "<BLOCKQUOTE>\n".
  383.         "If you were using a java-enabled browser, ".
  384.         "you wouldn't see this!\n".
  385.         "</BLOCKQUOTE>\n".
  386.         "</APPLET>\n".
  387.         "</BODY></HTML>");
  388.  
  389. &ExpectWARN('PARAM can only appear in an APPLET element', '-x java',
  390.         "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  391.         "<PARAM NAME=\"text\" VALUE=\"This is the applet viewer.\">\n".
  392.         "</BODY></HTML>\n",
  393.         2, 'required-context');
  394.  
  395. &ExpectOK('valid use of netscape 2 markup', '-x netscape',
  396.       "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  397.       "<BODY>\n".
  398.       "<BIG>this is big text</BIG>\n".
  399.       "<SMALL>this is small text</SMALL>\n".
  400.       "<SUB>this is subscript text</SUB>\n".
  401.       "<SUP>this is superscript text</SUP>\n".
  402.       "<MAP NAME=\"map1\">\n".
  403.       "<AREA SHAPE=\"RECT\" COORDS=\"10,10,20,20\" HREF=\"foo.html\">\n".
  404.       "<AREA SHAPE=\"RECT\" COORDS=\"40,40,50,50\" NOHREF>\n".
  405.       "</MAP>\n".
  406.       "<IMG SRC=\"pic.gif\" ALT=map USEMAP=\"#map1\">\n".
  407.       "<FORM ENCTYPE=\"multipart/form-data\" ACTION=\"_URL_\" METHOD=POST>\n".
  408.       "<INPUT TYPE=submit VALUE=\"Send File\">\n".
  409.       "</FORM>\n".
  410.       "</BODY></HTML>");
  411.  
  412. &ExpectWARN('AREA can only appear in a MAP, MAP must have a NAME', '-x netscape',
  413.         "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  414.         "<AREA SHAPE=\"RECT\" COORDS=\"10,10,20,20\" HREF=\"foo.html\">\n".
  415.         "<MAP>\n".
  416.         "<AREA SHAPE=\"RECT\" COORDS=\"40,40,50,50\" NOHREF>\n".
  417.         "</MAP>\n".
  418.         "</BODY></HTML>\n",
  419.         2, 'required-context',
  420.         3, 'required-attribute');
  421.  
  422. &ExpectOK('non-empty list element, with comment last thing', '',
  423.       "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  424.       "<BODY>\n".
  425.       "<UL>\n".
  426.       "<LI>line 9\n".
  427.       "<!-- line 10 -->\n".
  428.       "<LI>line 11\n".
  429.       "</UL>\n".
  430.       "</BODY></HTML>");
  431.  
  432. &ExpectWARN('Enabling java extension should not enable netscape', '-x java',
  433.         "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n".
  434.         "Blah blah\n".
  435.         "</BODY></HTML>\n",
  436.         1, 'netscape-attribute');
  437.  
  438. &ExpectWARN("html which doesn't start with DOCTYPE", '-e require-doctype',
  439.         "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  440.         "<BODY>this is the body</BODY>\n</HTML>",
  441.         1, 'require-doctype');
  442.  
  443. &ExpectOK('html which starts with DOCTYPE', '-e require-doctype',
  444.       "<!DOCTYPE HTML PUBLIC '-//W3O//DTD WWW HTML 2.0//EN'>\n".
  445.       "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  446.       "<BODY>this is the body</BODY>\n</HTML>");
  447.  
  448. &ExpectWARN('should use > in place of >', '',
  449.         "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  450.         "<BODY>text with > instead of ></BODY>\n</HTML>",
  451.         3, 'literal-metacharacter');
  452.  
  453. &ExpectOK('IMG element with LOWSRC attribute', '-x netscape',
  454.       "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  455.       "<BODY>\n".
  456.       "<IMG SRC=\"foo.gif\" LOWSRC=\"lowfoo.gif\" ALT=\"alt text\">".
  457.       "</BODY>\n</HTML>");
  458.  
  459. &ExpectOK('Java applet and also using netscape extensions', '-x netscape,java',
  460.         "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  461.         "<BODY BACKGROUND=\"background.gif\">\n".
  462.         "<APPLET CODEBASE=\"http://java.sun.com/JDK-prebeta1/applets/NervousText\" CODE=\"NervousText.class\" WIDTH=400 HEIGHT=75 ALIGN=CENTER>\n".
  463.         "<PARAM NAME=\"text\" VALUE=\"This is the applet viewer.\">\n".
  464.         "<BLOCKQUOTE>\n".
  465.         "If you were using a java-enabled browser, ".
  466.         "you wouldn't see this!\n".
  467.         "</BLOCKQUOTE>\n".
  468.         "</APPLET>\n".
  469.         "</BODY></HTML>");
  470.  
  471. &ExpectWARN('text appearing in unexpected context', '',
  472.         "<HTML>\n".
  473.         "<HEAD>\n".
  474.         "Having text here is not legal!\n".
  475.         "<TITLE>test</TITLE></HEAD>\n".
  476.         "<BODY>\n".
  477.         "<UL>\n".
  478.         "Having text here is not legal!\n".
  479.         "</UL>\n".
  480.         "<OL>\n".
  481.         "Having text here is not legal!\n".
  482.         "</OL>\n".
  483.         "<DL>\n".
  484.         "Having text here is not legal!\n".
  485.         "</DL>\n".
  486.         "<TABLE>\n".
  487.         "Having text here is not legal!\n".
  488.         "<TR>\n".
  489.         "Having text here is not legal!\n".
  490.         "<TD>This is ok</TD>\n".
  491.         "</TR>\n".
  492.         "</TABLE>\n".
  493.         "</BODY></HTML>\n",
  494.         4, 'bad-text-context',
  495.         8, 'bad-text-context',
  496.         11, 'bad-text-context',
  497.         14, 'bad-text-context',
  498.         17, 'bad-text-context',
  499.         19, 'bad-text-context');
  500.  
  501. &ExpectWARN('IMG element with illegal value for ALIGN attribute', '',
  502.         "<HTML><HEAD><TITLE>foo</TITLE></HEAD><BODY>\n".
  503.         "<IMG SRC=foo.gif ALIGN=MODDLE ALT=\"alt text=\">\n".
  504.         "</BODY></HTML>",
  505.         2, 'attribute-format');
  506.  
  507. &ExpectOK('new netscape markup', '-x netscape',
  508.       "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  509.       "<BODY>\n".
  510.       "To <A HREF=\"foo.html\" TARGET=\"myWindow\">open a window</A>\n".
  511.       "<FONT COLOR=\"#00ff00\">blue text</FONT>\n".
  512.       "<FORM ACTION=\"foo.html\" METHOD=POST>\n".
  513.       "<TEXTAREA NAME=foo ROWS=24 COLS=24 WRAP=PHYSICAL>\n".
  514.       "hello</TEXTAREA>\n".
  515.       "</FORM>\n".
  516.       "</BODY>\n</HTML>");
  517.  
  518. &ExpectOK('valid FRAMESET example with FRAMES', '-x netscape',
  519.       "<HTML>\n<HEAD><TITLE>test</TITLE></HEAD>\n".
  520.       "<FRAMESET>\n".
  521.       "<FRAME SRC=\"cell.html\">\n".
  522.       "<FRAME SRC=\"cell.html\">\n".
  523.       "</FRAMESET>\n".
  524.       "</HTML>");
  525.  
  526. &ExpectWARN('FRAME outside of FRAMESET is illegal', '-x netscape',
  527.         "<HTML>\n".
  528.         "<HEAD><TITLE>test</TITLE></HEAD>\n".
  529.         "<BODY>\n".
  530.         "<FRAME SRC=\"cell.html\">\n".
  531.         "</BODY>\n".
  532.         "</HTML>",
  533.         4, 'required-context');
  534.  
  535. &ExpectOK('A valid JavaScript example', '-x netscape',
  536.       "<HTML>\n<HEAD><TITLE>test</TITLE>\n".
  537.       "<SCRIPT LANGUAGE=\"JavaScript\">\n".
  538.       "document.write(\"Hello net.\")\n".
  539.       "</SCRIPT>\n".
  540.       "</HEAD>\n".
  541.       "<BODY>\n".
  542.       "That's all, folks.\n".
  543.       "</BODY>\n".
  544.       "</HTML>");
  545.  
  546. &ExpectOK('FORM element with SELECT element which has SIZE attribute', '',
  547.       "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  548.       "<BODY>\n".
  549.       "<FORM METHOD=post ACTION=\"http://www.khoral.com/foo\">\n".
  550.       "<SELECT NAME=\"foobar\" SIZE=\"50,8\">\n".
  551.       "<OPTION>foobar\n".
  552.       "</SELECT>\n".
  553.       "</FORM></BODY></HTML>");
  554.  
  555. &ExpectOK('HR element can have percentage width in netscape', '-x netscape',
  556.       "<HTML>\n<HEAD><TITLE>title</TITLE></HEAD>\n".
  557.       "<BODY>\n".
  558.       "<HR WIDTH=\"50%\">\n".
  559.       "</BODY></HTML>");
  560.  
  561. &WeblintTestEnd();
  562.  
  563.  
  564. #========================================================================
  565. # Function:    ExpectOK
  566. # Purpose:    This is the high-level interface to the checker.  It takes
  567. #        a file and checks for fluff.
  568. #========================================================================
  569. sub ExpectOK
  570. {
  571.    local($description, $flags, $html) = @_;
  572.    local(@results);
  573.  
  574.  
  575.    &NextTest($description);
  576.    &CreateFile($html) || die "Failed to create working file ($filename): $!\n";
  577.    @results = &RunWeblint($flags);
  578.    if (@results == 0)
  579.    {
  580.       &TestPasses();
  581.    }
  582.    else
  583.    {
  584.       &TestFails($html, @results);
  585.    }
  586. }
  587.  
  588.  
  589. #========================================================================
  590. # Function:    ExpectWARN
  591. # Purpose:    A test which we expect weblint to complain about.
  592. #        We pass in one or more expected errors.
  593. #========================================================================
  594. sub ExpectWARN
  595. {
  596.    local($description, $flags, $html, @expected) = @_;
  597.    local(@results, @notSeen);
  598.    local($i, $j);
  599.  
  600.  
  601.    &NextTest($description);
  602.    &CreateFile($html) || die "Failed to create working file ($filename): $!\n";
  603.    @results = &RunWeblint($flags);
  604.  
  605.    if (@results == 0)
  606.    {
  607.       &TestFails($html);
  608.       return;
  609.    }
  610.  
  611.    OUTER: for ($i=0; $i < $#expected; $i += 2)
  612.    {
  613.       INNER: for ($j = 0; $j < $#results; $j += 2)
  614.       {
  615.      if ($results[$j] == $expected[$i] &&
  616.          $results[$j+1] eq $expected[$i+1])
  617.      {
  618.         @lost = splice(@results, $j, 2);
  619.         next OUTER;
  620.      }
  621.       }
  622.       @notSeen = (@notSeen, $expected[$i], $expected[$i+1]);
  623.    }
  624.  
  625.    if (@notSeen == 0 && @results == 0)
  626.    {
  627.       &TestPasses();
  628.    }
  629.    else
  630.    {
  631.       &TestFails($html, @results);
  632.    }
  633. }
  634.  
  635.  
  636. #========================================================================
  637. # Function:    RunWeblint
  638. # Purpose:    This function runs weblint and parses the output.
  639. #        The results from weblint are passed back in an array.
  640. #========================================================================
  641. sub RunWeblint
  642. {
  643.    local($flags) = @_;
  644.    local(*OUTPUT);
  645.    local(@results);
  646.  
  647.  
  648.    open(OUTPUT, "./weblint -t $flags $filename |") || do
  649.    {
  650.       die "Failed to create pipe from weblint: $!\n";
  651.    };
  652.    while (<OUTPUT>)
  653.    {
  654.       next if /^$/;
  655.       chop;
  656.       ($repfile, $line, $wid) = split(/:/);
  657.       push(@results, $line, $wid);
  658.    }
  659.    close OUTPUT;
  660.    $status = ($? >> 8);
  661.  
  662.    return @results;
  663. }
  664.  
  665.  
  666. #========================================================================
  667. # Function:    CreateFile
  668. # Purpose:    Create sample html file from text string.
  669. #========================================================================
  670. sub CreateFile
  671. {
  672.    local($html) = @_;
  673.    local(*FILE);
  674.  
  675.  
  676.    open(FILE, "> $filename") || return undef;
  677.    print FILE $html."\n";
  678.    close FILE;
  679.  
  680.    1;
  681. }
  682.  
  683. #========================================================================
  684. # Function:    WeblintTestInitialize()
  685. # Purpose:    Initialize global variables and open log file.
  686. #========================================================================
  687. sub WeblintTestInitialize
  688. {
  689.    $TMPDIR   = &PickTmpdir(@TMPDIR_OPTIONS);
  690.    $WORKDIR  = "$TMPDIR/weblint-test.$$";
  691.    mkdir($WORKDIR, 0755) || do
  692.    {
  693.       die "Failed to create working directory $WORKDIR: $!\n";
  694.    };
  695.  
  696.    $filename = $WORKDIR.'/'.$FILENAME;
  697.    $testID   = 0;
  698.    $failCount = 0;
  699.    $passCount = 0;
  700.  
  701.    $WEBLINTVERSION = &DetermineWeblintVersion() || 'could not determine';
  702.  
  703.    open(LOGFILE, "> $LOGFILE") || die "Can't write logfile $LOGFILE: $!\n";
  704.  
  705.    print LOGFILE "Weblint Testsuite:\n";
  706.    print LOGFILE "    Weblint Version:   $WEBLINTVERSION\n";
  707.    print LOGFILE "    Testsuite Version: $VERSION\n";
  708.    print LOGFILE '=' x 76, "\n";
  709.  
  710.    print STDERR "Running weblint testsuite:\n";
  711.    print STDERR "    Weblint Version:   $WEBLINTVERSION\n";
  712.    print STDERR "    Testsuite Version: $VERSION\n";
  713.    print STDERR "    Results Logfile:   $LOGFILE\n";
  714.    print STDERR "Running test cases (. for pass, ! for failure):\n";
  715. }
  716.  
  717. #========================================================================
  718. # Function:    WeblintTestEnd()
  719. # Purpose:    Generate summary in logfile, close logfile, then
  720. #        clean up working files and directory.
  721. #========================================================================
  722. sub DetermineWeblintVersion
  723. {
  724.    local(*PIPE);
  725.    local($VERSION);
  726.  
  727.    open(PIPE, "./weblint -v 2>&1 |") || return undef;
  728.  
  729.    while (<PIPE>)
  730.    {
  731.       return $1 if /^(weblint\s+v.*)$/;
  732.  
  733.       /^\s*This is weblint, version\s*([0-9.]+)/ && do
  734.       {
  735.      return "weblint v$1";
  736.       };
  737.    }
  738. }
  739.  
  740. #========================================================================
  741. # Function:    WeblintTestEnd()
  742. # Purpose:    Generate summary in logfile, close logfile, then
  743. #        clean up working files and directory.
  744. #========================================================================
  745. sub WeblintTestEnd
  746. {
  747.    print LOGFILE '=' x 76, "\n";
  748.    print LOGFILE "Number of Passes:   $passCount\n";
  749.    print LOGFILE "Number of Failures: $failCount\n";
  750.    close LOGFILE;
  751.  
  752.    print STDERR "\n", '-' x 76, "\n";
  753.    if ($failCount > 0)
  754.    {
  755.       print STDERR "Failed tests:\n";
  756.       foreach $failure (@failedTests)
  757.       {
  758.      print STDERR "    $failure\n";
  759.       }
  760.       print STDERR '-' x 76, "\n";
  761.       
  762.    }
  763.    print STDERR "Number of Passes:   $passCount\n";
  764.    print STDERR "Number of Failures: $failCount\n";
  765.  
  766.    unlink $filename;
  767.    rmdir $WORKDIR;
  768. }
  769.  
  770. #========================================================================
  771. # Function:    NextTest()
  772. # Purpose:    Introduce a new test -- increment test id, write
  773. #        separator and test information to log file.
  774. #========================================================================
  775. sub NextTest
  776. {
  777.    local($description) = @_;
  778.  
  779.  
  780.    ++$testID;
  781.    print LOGFILE '-' x 76, "\n";
  782.    $testDescription = $description;
  783. }
  784.  
  785. #========================================================================
  786. # Function:    TestPasses()
  787. # Purpose:    The current test passed.  Write result to logfile, and
  788. #        increment the count of successful tests.
  789. #========================================================================
  790. sub TestPasses
  791. {
  792.    printf LOGFILE ("%3d %s%s%s", $testID, $testDescription,
  793.            ' ' x (68 - length($testDescription)), "PASS\n");
  794.    # printf STDERR "%3d: pass (%s)\n", $testID, $testDescription;
  795.    print STDERR ".";
  796.    ++$passCount;
  797. }
  798.  
  799. #========================================================================
  800. # Function:    TestFails()
  801. # Purpose:    The current test failed.  Write result to logfile,
  802. #        including the html which failed, and the output from weblint.
  803. #========================================================================
  804. sub TestFails
  805. {
  806.    local($html, @results) = @_;
  807.    local($string);
  808.  
  809.  
  810.    # printf STDERR "%3d: FAIL (%s)\n", $testID, $testDescription;
  811.    $string = sprintf("%3d: %s", $testID, $testDescription);
  812.    push(@failedTests, $string);
  813.    print STDERR "!";
  814.  
  815.    printf LOGFILE ("%3d %s%s%s", $testID, $testDescription,
  816.            ' ' x (68 - length($testDescription)), "FAIL\n");
  817.  
  818.    $html =~ s/\n/\n    /g;
  819.    print LOGFILE "\n  HTML:\n    $html\n\n";
  820.    print LOGFILE "  WEBLINT OUTPUT:\n";
  821.    while (@results > 1)
  822.    {
  823.       ($line, $wid) = splice(@results, 0, 2);
  824.       print LOGFILE "    line $line: $wid\n";
  825.    }
  826.    print LOGFILE "\n";
  827.    ++$failCount;
  828. }
  829.  
  830. #========================================================================
  831. # Function:    PickTmpdir
  832. # Purpose:    Pick a temporary working directory. If TMPDIR environment
  833. #        variable is set, then we try that first.
  834. #========================================================================
  835. sub PickTmpdir
  836. {
  837.    local(@options) = @_;
  838.    local($tmpdir);
  839.  
  840.    @options = ($ENV{'TMPDIR'}, @options) if defined $ENV{'TMPDIR'};
  841.    foreach $tmpdir (@options)
  842.    {
  843.       return $tmpdir if -d $tmpdir && -w $tmpdir;
  844.    }
  845.    die "$PROGRAM: unable to find a temporary directory.\n",
  846.        ' ' x (length($PROGRAM)+2), "tried: ",join(' ',@options),"\n";
  847. }
  848.