funit 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ module Funit
2
+
3
+ ##
4
+ # Fortran compiler
5
+
6
+ class Compiler
7
+
8
+ def initialize
9
+ error_message = <<-COMPILER
10
+ Fortran compiler environment variable 'FC' not set.
11
+
12
+ For example, if you had the g95 compiler:
13
+
14
+ sh: export FC=g95
15
+ csh: setenv FC g95
16
+ windows: set FC=C:\\Program Files\\g95
17
+ COMPILER
18
+ raise error_message unless ENV['FC']
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ #--
26
+ # Copyright 2006-2007 United States Government as represented by
27
+ # NASA Langley Research Center. No copyright is claimed in
28
+ # the United States under Title 17, U.S. Code. All Other Rights
29
+ # Reserved.
30
+ #
31
+ # This file is governed by the NASA Open Source Agreement.
32
+ # See License.txt for details.
33
+ #++
@@ -0,0 +1,100 @@
1
+ require 'erb'
2
+
3
+ module Funit
4
+
5
+ TEST_RUNNER = ERB.new %q{
6
+ ! TestRunner.f90 - runs fUnit test suites
7
+ !
8
+ ! <%= File.basename $0 %> generated this file on <%= Time.now %>.
9
+
10
+ program TestRunner
11
+ <%= test_suites.inject('') { |result,test_suite| result << "\n use #{test_suite}_fun" } %>
12
+
13
+ implicit none
14
+
15
+ integer :: numTests, numAsserts, numAssertsTested, numFailures
16
+
17
+ <% test_suites.each do |ts| %>
18
+ print *, ""
19
+ print *, "<%= ts %> test suite:"
20
+ call test_<%= ts %> &
21
+ ( numTests, numAsserts, numAssertsTested, numFailures )
22
+ print *, "Passed", numAssertsTested, "of", numAsserts, &
23
+ "possible asserts comprising", &
24
+ numTests-numFailures, "of", numTests, "tests."
25
+ <% end %>
26
+ print *, ""
27
+
28
+ end program TestRunner
29
+ }.gsub(/^/,' '), nil, '<>' # turn off newlines due to <%%>
30
+
31
+ def requested_modules(module_names)
32
+ if (module_names.empty?)
33
+ module_names = Dir["*.fun"].each{ |mod| mod.chomp! ".fun" }
34
+ end
35
+ module_names
36
+ end
37
+
38
+ def funit_exists?(module_name)
39
+ File.exists? "#{module_name}.fun"
40
+ end
41
+
42
+ def parse_command_line
43
+
44
+ module_names = requested_modules(ARGV)
45
+
46
+ if module_names.empty?
47
+ raise " *Error: no test suites found in this directory"
48
+ end
49
+
50
+ module_names.each do |mod|
51
+ unless funit_exists?(mod)
52
+ error_message = <<-FUNITDOESNOTEXIST
53
+ Error: could not find test suite #{mod}.fun
54
+ Test suites available in this directory:
55
+ #{requested_modules([]).join(' ')}
56
+
57
+ Usage: #{File.basename $0} [test names (w/o .fun suffix)]
58
+ FUNITDOESNOTEXIST
59
+ raise error_message
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ def write_test_runner test_suites
66
+ File.open("TestRunner.f90", "w") do |file|
67
+ file.puts TEST_RUNNER.result(binding)
68
+ end
69
+ end
70
+
71
+ def syntax_error( message, test_suite )
72
+ raise "\n *Error: #{message} [#{test_suite}.fun:#$.]\n\n"
73
+ end
74
+
75
+ def warning( message, test_suite )
76
+ $stderr.puts "\n *Warning: #{message} [#{test_suite}.fun:#$.]"
77
+ end
78
+
79
+ def compile_tests test_suites
80
+ puts "computing dependencies"
81
+ dependencies = Fortran::Dependencies.new
82
+ puts "locating associated source files and sorting for compilation"
83
+ required_sources = dependencies.required_source_files('TestRunner.f90')
84
+
85
+ puts compile = "#{ENV['FC']} #{ENV['FCFLAGS']} -o TestRunner \\\n #{required_sources.join(" \\\n ")}"
86
+
87
+ raise "Compile failed." unless system compile
88
+ end
89
+
90
+ end
91
+
92
+ #--
93
+ # Copyright 2006-2007 United States Government as represented by
94
+ # NASA Langley Research Center. No copyright is claimed in
95
+ # the United States under Title 17, U.S. Code. All Other Rights
96
+ # Reserved.
97
+ #
98
+ # This file is governed by the NASA Open Source Agreement.
99
+ # See License.txt for details.
100
+ #++
@@ -0,0 +1,197 @@
1
+ require 'funit/assertions'
2
+ require 'funit/functions'
3
+ require 'ftools' # FIXME: use fileutils
4
+
5
+ module Funit
6
+
7
+ include Assertions # FIXME
8
+
9
+ ##
10
+ # Create testsuite wrapper code
11
+
12
+ class TestSuite < File
13
+
14
+ ASSERTION_PATTERN = /Is(RealEqual|False|True|EqualWithin|Equal)\(.*\)/i
15
+ KEYWORDS = /(begin|end)(Setup|Teardown|Test)|Is(RealEqual|Equal|False|True|EqualWithin)\(.*\)/i
16
+ COMMENT_LINE = /^\s*!/
17
+
18
+ include Funit #FIXME
19
+
20
+ def initialize suite_name
21
+ @line_number = 'blank'
22
+ @suite_name = suite_name
23
+ return nil unless funit_exists?(suite_name)
24
+ File.delete(suite_name+"_fun.f90") if File.exists?(suite_name+"_fun.f90")
25
+ super(suite_name+"_fun.f90","w")
26
+ @tests, @setup, @teardown = [], [], []
27
+ top_wrapper
28
+ expand
29
+ close
30
+ end
31
+
32
+ def top_wrapper
33
+ puts <<-TOP
34
+ ! #{@suite_name}_fun.f90 - a unit test suite for #{@suite_name}.f90
35
+ !
36
+ ! #{File.basename $0} generated this file from #{@suite_name}.fun
37
+ ! at #{Time.now}
38
+
39
+ module #{@suite_name}_fun
40
+
41
+ use #{@suite_name}
42
+
43
+ implicit none
44
+
45
+ logical :: noAssertFailed
46
+
47
+ public :: test_#@suite_name
48
+
49
+ private
50
+
51
+ integer :: numTests = 0
52
+ integer :: numAsserts = 0
53
+ integer :: numAssertsTested = 0
54
+ integer :: numFailures = 0
55
+
56
+ TOP
57
+ end
58
+
59
+ def expand
60
+ funit_file = @suite_name+".fun"
61
+ $stderr.print "expanding #{funit_file}..."
62
+
63
+ funit_contents = IO.readlines(funit_file)
64
+ @funit_total_lines = funit_contents.length
65
+
66
+ while (line = funit_contents.shift) && line !~ KEYWORDS
67
+ puts line
68
+ end
69
+
70
+ funit_contents.unshift line
71
+
72
+ puts " contains\n\n"
73
+
74
+ while (line = funit_contents.shift)
75
+ case line
76
+ when COMMENT_LINE
77
+ puts line
78
+ when /beginSetup/i
79
+ add_to_setup funit_contents
80
+ when /beginTeardown/i
81
+ add_to_teardown funit_contents
82
+ when /XbeginTest\s+(\w+)/i
83
+ ignore_test($1,funit_contents)
84
+ when /beginTest\s+(\w+)/i
85
+ a_test($1,funit_contents)
86
+ when /beginTest/i
87
+ syntax_error "no name given for beginTest", @suite_name
88
+ when /end(Setup|Teardown|Test)/i
89
+ syntax_error "no matching begin#$1 for an #$&", @suite_name
90
+ when ASSERTION_PATTERN
91
+ syntax_error "#$1 assert not in a test block", @suite_name
92
+ else
93
+ puts line
94
+ end
95
+ end
96
+ $stderr.puts "done."
97
+ end
98
+
99
+ def add_to_setup funit_contents
100
+ while (line = funit_contents.shift) && line !~ /endSetup/i
101
+ @setup.push line
102
+ end
103
+ end
104
+
105
+ def add_to_teardown funit_contents
106
+ while (line = funit_contents.shift) && line !~ /endTeardown/i
107
+ @teardown.push line
108
+ end
109
+ end
110
+
111
+ def ignore_test test_name, funit_contents
112
+ warning("Ignoring test: #{test_name}", @suite_name)
113
+ line = funit_contents.shift while line !~ /endTest/i
114
+ end
115
+
116
+ def a_test test_name, funit_contents
117
+ @test_name = test_name
118
+ @tests.push test_name
119
+ syntax_error("test name #@test_name not unique",@suite_name) if (@tests.uniq!)
120
+
121
+ puts " subroutine #{test_name}\n\n"
122
+
123
+ num_of_asserts = 0
124
+
125
+ while (line = funit_contents.shift) && line !~ /endTest/i
126
+ case line
127
+ when COMMENT_LINE
128
+ puts line
129
+ when /Is(RealEqual|False|True|EqualWithin|Equal)/i
130
+ @line_number = @funit_total_lines - funit_contents.length
131
+ num_of_asserts += 1
132
+ puts send( $&.downcase!, line )
133
+ else
134
+ puts line
135
+ end
136
+ end
137
+ warning("no asserts in test", @suite_name) if num_of_asserts == 0
138
+
139
+ puts "\n numTests = numTests + 1\n\n"
140
+ puts " end subroutine #{test_name}\n\n"
141
+ end
142
+
143
+ def close
144
+ puts "\n subroutine Setup"
145
+ puts @setup
146
+ puts " noAssertFailed = .true."
147
+ puts " end subroutine Setup\n\n"
148
+
149
+ puts "\n subroutine Teardown"
150
+ puts @teardown
151
+ puts " end subroutine Teardown\n\n"
152
+
153
+ puts <<-NEXTONE
154
+
155
+ subroutine test_#{@suite_name}( nTests, nAsserts, nAssertsTested, nFailures )
156
+
157
+ integer :: nTests
158
+ integer :: nAsserts
159
+ integer :: nAssertsTested
160
+ integer :: nFailures
161
+
162
+ continue
163
+ NEXTONE
164
+
165
+ @tests.each do |test_name|
166
+ puts "\n call Setup"
167
+ puts " call #{test_name}"
168
+ puts " call Teardown"
169
+ end
170
+
171
+ puts <<-LASTONE
172
+
173
+ nTests = numTests
174
+ nAsserts = numAsserts
175
+ nAssertsTested = numAssertsTested
176
+ nFailures = numFailures
177
+
178
+ end subroutine test_#{@suite_name}
179
+
180
+ end module #{@suite_name}_fun
181
+ LASTONE
182
+ super
183
+ end
184
+
185
+ end
186
+
187
+ end
188
+
189
+ #--
190
+ # Copyright 2006-2007 United States Government as represented by
191
+ # NASA Langley Research Center. No copyright is claimed in
192
+ # the United States under Title 17, U.S. Code. All Other Rights
193
+ # Reserved.
194
+ #
195
+ # This file is governed by the NASA Open Source Agreement.
196
+ # See License.txt for details.
197
+ #++
@@ -0,0 +1,16 @@
1
+ require 'test/unit'
2
+ require 'funit/compiler'
3
+
4
+ class TestCompiler < Test::Unit::TestCase
5
+
6
+ def test_no_environment_compiler_name
7
+ begin
8
+ orig_FC = ENV['FC']
9
+ ENV['FC'] = nil
10
+ assert_raises(RuntimeError) {Funit::Compiler.new}
11
+ ensure
12
+ ENV['FC'] = orig_FC
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,10 @@
1
+ require 'test/unit'
2
+ require 'funit/functions'
3
+
4
+ class TestFunctions < Test::Unit::TestCase
5
+
6
+ def test_something
7
+ # FIXME
8
+ end
9
+
10
+ end
@@ -0,0 +1,113 @@
1
+ require 'test/unit'
2
+ require 'funit'
3
+ require 'ftools' # FIXME: migrate to fileutils
4
+
5
+ class TestFunit < Test::Unit::TestCase
6
+
7
+ include Funit # FIXME
8
+ include Funit::Assertions # FIXME
9
+
10
+ def setup
11
+ File.rm_f(*Dir["dummyunit*"])
12
+ File.rm_f(*Dir["unit*"])
13
+ File.rm_f(*Dir["ydsbe*"])
14
+ File.rm_f(*Dir["lmzd*"])
15
+ File.rm_f(*Dir["ldfdl*"])
16
+ File.rm_f(*Dir["ydsbe*"])
17
+ File.rm_f(*Dir["TestRunner*"])
18
+ File.rm_f(*Dir["a.out"])
19
+ end
20
+
21
+ def teardown
22
+ File.rm_f(*Dir["dummyunit*"])
23
+ File.rm_f(*Dir["unit*"])
24
+ File.rm_f(*Dir["ydsbe*"])
25
+ File.rm_f(*Dir["lmzd*"])
26
+ File.rm_f(*Dir["ldfdl*"])
27
+ File.rm_f(*Dir["ydsbe*"])
28
+ File.rm_f(*Dir["TestRunner*"])
29
+ File.rm_f(*Dir["a.out"])
30
+ end
31
+
32
+ def test_main_driver_compiles
33
+ write_test_runner []
34
+ assert File.exists?("TestRunner.f90")
35
+ assert system("#{ENV['FC']} TestRunner.f90")
36
+ assert File.exists?("a.out")
37
+ end
38
+
39
+ def test_is_equal
40
+ @suite_name = "dummy"
41
+ @test_name = "dummy"
42
+ @line_number = "dummy"
43
+ isequal("IsEqual(1.0,m(1,1))")
44
+ assert_equal '.not.(1.0==m(1,1))', @condition
45
+ end
46
+
47
+ def test_is_real_equal
48
+ @suite_name = "dummy"
49
+ @test_name = "dummy"
50
+ @line_number = "dummy"
51
+ isrealequal("IsRealEqual(a,b)")
52
+ ans = <<-EOF
53
+ .not.(a+2*spacing(real(a)).ge.b &
54
+ .and.a-2*spacing(real(a)).le.b)
55
+ EOF
56
+ assert_equal ans.chomp, @condition
57
+ assert_equal '"b (",b,") is not",a,"within",2*spacing(real(a))', @message
58
+ isrealequal("IsRealEqual(1.0,m(1,1))")
59
+ ans = <<-EOF
60
+ .not.(1.0+2*spacing(real(1.0)).ge.m(1,1) &
61
+ .and.1.0-2*spacing(real(1.0)).le.m(1,1))
62
+ EOF
63
+ assert_equal ans.chomp, @condition
64
+ end
65
+
66
+ def test_handles_dependency
67
+ File.open('unit.f90','w') do |f|
68
+ f.printf "module unit\n use unita, only : a\nend module unit\n"
69
+ end
70
+ File.open('unita.f90','w') do |f|
71
+ f.printf "module unita\n integer :: a = 5\nend module unita\n"
72
+ end
73
+ File.open('unit.fun','w') do |f|
74
+ f.printf "beginTest a_gets_set\n IsEqual(5, a)\nendTest\n"
75
+ end
76
+ assert_nothing_raised{run_tests}
77
+ end
78
+
79
+ def test_embedded_dependencies
80
+ File.open('unit.f90','w') do |f|
81
+ f.printf "module unit\n use unita, only : a\nend module unit\n"
82
+ end
83
+ File.open('unita.f90','w') do |f|
84
+ f.printf "module unita\n use unitb, only : b \n integer :: a = b\nend module unita\n"
85
+ end
86
+ File.open('unitb.f90','w') do |f|
87
+ f.printf "module unitb\n integer,parameter :: b = 5\nend module unitb\n"
88
+ end
89
+ File.open('unit.fun','w') do |f|
90
+ f.printf "beginTest a_gets_set\n IsEqual(5, a)\nendTest\n"
91
+ end
92
+ assert_nothing_raised{run_tests}
93
+ end
94
+
95
+ def test_requested_modules
96
+ assert_equal ["asdfga"], requested_modules(["asdfga"])
97
+ assert_equal ["asd","fga"], requested_modules(["asd","fga"])
98
+ assert requested_modules([]).empty?
99
+ modules = %w[ldfdl lmzd]
100
+ funits = modules.map{|f| f+'.fun'}.join(' ')
101
+ system "touch "+funits
102
+ assert_equal modules, requested_modules([])
103
+ end
104
+
105
+ def test_funit_exists_method
106
+ module_name = "ydsbe"
107
+ File.rm_f(module_name+".fun")
108
+ assert_equal false, funit_exists?(module_name)
109
+ system "touch "+module_name+".fun"
110
+ assert funit_exists?(module_name)
111
+ end
112
+
113
+ end