[FIX] Clean up/minimize VisualBasic sample code for parser test; remove IBM licensing
[ohcount] / test / test_helper.rb
1 require 'test/unit'
2 require 'fileutils'
3 require 'find'
4
5 TEST_DIR = File.dirname(__FILE__)
6 require TEST_DIR + '/../lib/ohcount'
7
8 # Ohcount::Test is a base class which includes several helper methods for parser testing.
9 # All unit tests in Ohcount should derive from this class.
10 #
11 # ==== Manual Testing
12 #
13 # To manually test a parser, rebuild ohcount and run it against your test file:
14
15 #   rake
16 #   bin/ohcount --annotate test/src_dir/my_file.ext
17
18 # The +annotate+ option will emit your test file to the console, and each line will be
19 # labeled as code, comment, or blank.
20 #
21 class Ohcount::Test < Test::Unit::TestCase
22
23         # For reasons unknown, the base class defines a default_test method to throw a failure.
24         # We override it with a no-op to prevent this 'helpful' feature.
25         def default_test
26         end
27
28         def src_dir
29                 TEST_DIR + "/src_dir"
30         end
31
32         def scratch_dir
33                 TEST_DIR + "/scratch_dir"
34         end
35
36         def expected_dir
37                 TEST_DIR + "/expected_dir"
38         end
39
40         # verify_parse runs a full test against a specified file. Detector is used to determine
41         # the correct parser, then the file is parsed and compared against expected results.
42         #
43         # The file to be parsed must be in directory <tt>test/src_dir</tt>.
44         #
45         # The expected results must be stored on disk in directory <tt>test/expected_dir</tt>. The format
46         # of the expected results on disk is a bit cumbersome. To create new test case, you must:
47         #
48         # 1. Create a new source code file in <tt>test/src_dir</tt>.
49         #    For example, <tt>test/src_dir/my_file.ext</tt>
50         #
51         # 2. Next, create a new directory in <tt>test/expected_dir</tt> with
52         #    the same name as your test source code file. For example,
53         #    <tt>test/expected_dir/my_file.ext/</tt>
54         #
55         # 3. Within this directory, create directories for each language used in the test source code
56         #    file. For example, <tt>test/expected_dir/my_file.ext/my_language/</tt>
57         #
58         # 4. In this language subdirectory, create three files called +code+, +comment+, and +blanks+.
59         #    The +code+ file should contain all of the lines from <tt>my_file.ext</tt> which are code lines.
60         #    The +comment+ file should contain all comment lines.
61         #    The +blanks+ file is a bit different: it should contain a single line with an integer
62         #    which is the count of blank lines in the original file.
63         #
64         # There are numerous examples in the test directories to help you out.
65         #
66         def verify_parse(src_filename, filenames = [])
67                 # re-make the output directory
68                 Dir.mkdir scratch_dir unless File.exists? scratch_dir
69                 output_dir = scratch_dir + "/#{ File.basename(src_filename) }"
70                 FileUtils.rm_r(output_dir) if FileTest.directory?(output_dir)
71                 Dir.mkdir output_dir
72
73                 complete_src_filename = src_dir + "/#{ src_filename }"
74     sfc = Ohcount::SimpleFileContext.new(complete_src_filename, filenames)
75                 polyglot = Ohcount::Detector.detect(sfc)
76
77                 # parse
78                 buffer = File.new(complete_src_filename).read
79                 Ohcount::Parser.parse_to_dir(:dir => output_dir,
80                                                                                                                                 :buffer => buffer,
81                                                                                                                                 :polyglot => polyglot)
82
83                 # now compare
84                 answer_dir = expected_dir + "/#{ File.basename(src_filename) }"
85                 compare_dir(answer_dir, output_dir)
86
87                 # just to be sure, lets compare the total number of lines from the source file and the processed breakdown
88                 compare_line_count(complete_src_filename, output_dir)
89         end
90
91
92         def compare_dir(expected, actual)
93                 # make sure entries are identical
94                 expected_entries = expected.entries.collect { |e| e[expected.size..-1] }
95                 actual_entries = actual.entries.collect { |a| a[actual.size..-1] }
96                 assert_equal expected_entries, actual_entries
97
98                 Dir.foreach(expected) do |entry|
99                         next if [".", "..", ".svn"].include?(entry)
100                         case File.ftype(expected+ "/" + entry)
101                         when 'file'
102                                 File.open(expected + "/" + entry) do |e|
103                                         File.open(actual + "/" + entry) do |a|
104                                                 assert_equal e.read, a.read, "file #{actual + "/" + entry} differs from expected"
105                                         end
106                                 end
107                         when 'directory'
108                                 compare_dir(expected + "/" + entry, actual + "/" + entry)
109                         else
110                                 assert false, "weird ftype"
111                         end
112                 end
113         end
114
115
116         def compare_line_count(src_file, scratch_dir)
117                 code_lines = comment_lines = blanks = 0
118
119                 Find.find(scratch_dir) do |path|
120                         if FileTest.file?(path)
121                                 `wc -l #{ path }` =~ /^\s*(\d*)\b/
122                                 case File.basename(path)
123                                 when 'code'
124                                         code_lines += $1.to_i
125                                 when 'comment'
126                                         comment_lines += $1.to_i
127                                 when 'blanks'
128                                         blanks += File.new(path).read.to_i
129                                 end
130                         end
131                 end
132
133                 # src file lines
134                 `wc -l #{ src_file }` =~ /^\s*(\d*)\b/
135                 src_file_lines = $1.to_i
136
137                 # compare
138                 assert_equal src_file_lines, (code_lines + comment_lines + blanks), "wc -l of output (code, comment, blanks) doesn't match the 'wc -l' of original"
139         end
140 end
141