stamina 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/CHANGELOG.md +22 -5
  2. data/LICENCE.md +2 -2
  3. data/bin/stamina +1 -7
  4. data/lib/stamina.rb +10 -19
  5. metadata +54 -333
  6. data/.gemtest +0 -0
  7. data/Gemfile +0 -2
  8. data/Gemfile.lock +0 -37
  9. data/Manifest.txt +0 -16
  10. data/README.md +0 -78
  11. data/Rakefile +0 -23
  12. data/example/adl/automaton.adl +0 -49
  13. data/example/adl/sample.adl +0 -53
  14. data/example/basic/characteristic_sample.adl +0 -32
  15. data/example/basic/target.adl +0 -9
  16. data/example/competition/31_test.adl +0 -1500
  17. data/example/competition/31_training.adl +0 -1759
  18. data/lib/stamina/abbadingo.rb +0 -2
  19. data/lib/stamina/abbadingo/random_dfa.rb +0 -48
  20. data/lib/stamina/abbadingo/random_sample.rb +0 -146
  21. data/lib/stamina/adl.rb +0 -298
  22. data/lib/stamina/automaton.rb +0 -1263
  23. data/lib/stamina/automaton/complete.rb +0 -36
  24. data/lib/stamina/automaton/equivalence.rb +0 -55
  25. data/lib/stamina/automaton/metrics.rb +0 -78
  26. data/lib/stamina/automaton/minimize.rb +0 -25
  27. data/lib/stamina/automaton/minimize/hopcroft.rb +0 -116
  28. data/lib/stamina/automaton/minimize/pitchies.rb +0 -64
  29. data/lib/stamina/automaton/strip.rb +0 -16
  30. data/lib/stamina/automaton/walking.rb +0 -363
  31. data/lib/stamina/classifier.rb +0 -52
  32. data/lib/stamina/command.rb +0 -45
  33. data/lib/stamina/command/abbadingo_dfa.rb +0 -81
  34. data/lib/stamina/command/abbadingo_samples.rb +0 -40
  35. data/lib/stamina/command/adl2dot.rb +0 -71
  36. data/lib/stamina/command/classify.rb +0 -48
  37. data/lib/stamina/command/help.rb +0 -27
  38. data/lib/stamina/command/infer.rb +0 -141
  39. data/lib/stamina/command/metrics.rb +0 -51
  40. data/lib/stamina/command/robustness.rb +0 -22
  41. data/lib/stamina/command/score.rb +0 -35
  42. data/lib/stamina/errors.rb +0 -23
  43. data/lib/stamina/ext/math.rb +0 -20
  44. data/lib/stamina/induction/blue_fringe.rb +0 -265
  45. data/lib/stamina/induction/commons.rb +0 -156
  46. data/lib/stamina/induction/rpni.rb +0 -186
  47. data/lib/stamina/induction/union_find.rb +0 -377
  48. data/lib/stamina/input_string.rb +0 -123
  49. data/lib/stamina/loader.rb +0 -1
  50. data/lib/stamina/markable.rb +0 -42
  51. data/lib/stamina/sample.rb +0 -267
  52. data/lib/stamina/scoring.rb +0 -213
  53. data/lib/stamina/utils.rb +0 -1
  54. data/lib/stamina/utils/decorate.rb +0 -81
  55. data/lib/stamina/version.rb +0 -14
  56. data/stamina.gemspec +0 -191
  57. data/stamina.noespec +0 -32
  58. data/tasks/debug_mail.rake +0 -78
  59. data/tasks/debug_mail.txt +0 -13
  60. data/tasks/gem.rake +0 -68
  61. data/tasks/spec_test.rake +0 -79
  62. data/tasks/unit_test.rake +0 -77
  63. data/tasks/yard.rake +0 -51
  64. data/test/stamina/abbadingo/random_dfa_test.rb +0 -16
  65. data/test/stamina/abbadingo/random_sample_test.rb +0 -78
  66. data/test/stamina/adl_test.rb +0 -516
  67. data/test/stamina/automaton/classifier_test.rb +0 -259
  68. data/test/stamina/automaton/complete_test.rb +0 -58
  69. data/test/stamina/automaton/equivalence_test.rb +0 -120
  70. data/test/stamina/automaton/metrics_test.rb +0 -36
  71. data/test/stamina/automaton/minimize/hopcroft_test.rb +0 -15
  72. data/test/stamina/automaton/minimize/minimize_test.rb +0 -55
  73. data/test/stamina/automaton/minimize/pitchies_test.rb +0 -15
  74. data/test/stamina/automaton/minimize/rice_edu_10.adl +0 -16
  75. data/test/stamina/automaton/minimize/rice_edu_10.min.adl +0 -13
  76. data/test/stamina/automaton/minimize/rice_edu_13.adl +0 -13
  77. data/test/stamina/automaton/minimize/rice_edu_13.min.adl +0 -7
  78. data/test/stamina/automaton/minimize/should_strip_1.adl +0 -8
  79. data/test/stamina/automaton/minimize/should_strip_1.min.adl +0 -6
  80. data/test/stamina/automaton/minimize/unknown_1.adl +0 -16
  81. data/test/stamina/automaton/minimize/unknown_1.min.adl +0 -12
  82. data/test/stamina/automaton/strip_test.rb +0 -36
  83. data/test/stamina/automaton/to_dot_test.rb +0 -64
  84. data/test/stamina/automaton/walking/dfa_delta_test.rb +0 -39
  85. data/test/stamina/automaton/walking_test.rb +0 -206
  86. data/test/stamina/automaton_additional_test.rb +0 -190
  87. data/test/stamina/automaton_test.rb +0 -1104
  88. data/test/stamina/exit.rb +0 -3
  89. data/test/stamina/induction/blue_fringe_test.rb +0 -83
  90. data/test/stamina/induction/induction_test.rb +0 -70
  91. data/test/stamina/induction/redblue_mergesamestatebug_expected.adl +0 -19
  92. data/test/stamina/induction/redblue_mergesamestatebug_pta.dot +0 -64
  93. data/test/stamina/induction/redblue_mergesamestatebug_sample.adl +0 -9
  94. data/test/stamina/induction/redblue_universal_expected.adl +0 -4
  95. data/test/stamina/induction/redblue_universal_sample.adl +0 -5
  96. data/test/stamina/induction/rpni_inria_expected.adl +0 -7
  97. data/test/stamina/induction/rpni_inria_sample.adl +0 -9
  98. data/test/stamina/induction/rpni_test.rb +0 -129
  99. data/test/stamina/induction/rpni_test_pta.dot +0 -22
  100. data/test/stamina/induction/rpni_universal_expected.adl +0 -4
  101. data/test/stamina/induction/rpni_universal_sample.adl +0 -4
  102. data/test/stamina/induction/union_find_test.rb +0 -124
  103. data/test/stamina/input_string_test.rb +0 -323
  104. data/test/stamina/markable_test.rb +0 -70
  105. data/test/stamina/randdfa.adl +0 -66
  106. data/test/stamina/sample.adl +0 -4
  107. data/test/stamina/sample_classify_test.rb +0 -149
  108. data/test/stamina/sample_test.rb +0 -290
  109. data/test/stamina/scoring_test.rb +0 -63
  110. data/test/stamina/small_dfa.dot +0 -16
  111. data/test/stamina/small_dfa.gif +0 -0
  112. data/test/stamina/small_nfa.dot +0 -18
  113. data/test/stamina/small_nfa.gif +0 -0
  114. data/test/stamina/stamina_test.rb +0 -80
  115. data/test/stamina/utils/decorate_test.rb +0 -65
  116. data/test/test_all.rb +0 -7
data/tasks/spec_test.rake DELETED
@@ -1,79 +0,0 @@
1
- # Installs a rake task for for running examples written using rspec.
2
- #
3
- # This file installs the 'rake spec_test' (aliased as 'rake spec') as well as
4
- # extends 'rake test' to run spec tests, if any. It is automatically generated
5
- # by Noe from your .noespec file, and should therefore be configured there,
6
- # under the variables/rake_tasks/spec_test entry, as illustrated below:
7
- #
8
- # variables:
9
- # rake_tasks:
10
- # spec_test:
11
- # pattern: spec/**/*_spec.rb
12
- # verbose: true
13
- # rspec_opts: [--color, --backtrace]
14
- # ...
15
- #
16
- # If you have specific needs requiring manual intervention on this file,
17
- # don't forget to set safe-override to false in your noe specification:
18
- #
19
- # template-info:
20
- # manifest:
21
- # tasks/spec_test.rake:
22
- # safe-override: false
23
- #
24
- # This file has been written to conform to RSpec v2.4.0. More information about
25
- # rspec and options of the rake task defined below can be found on
26
- # http://relishapp.com/rspec
27
- #
28
- begin
29
- require "rspec/core/rake_task"
30
- desc "Run RSpec code examples"
31
- RSpec::Core::RakeTask.new(:spec_test) do |t|
32
- # Glob pattern to match files.
33
- t.pattern = "spec/**/*_spec.rb"
34
-
35
- # By default, if there is a Gemfile, the generated command will include
36
- # 'bundle exec'. Set this to true to ignore the presence of a Gemfile,
37
- # and not add 'bundle exec' to the command.
38
- t.skip_bundler = false
39
-
40
- # Name of Gemfile to use
41
- t.gemfile = "Gemfile"
42
-
43
- # Whether or not to fail Rake when an error occurs (typically when
44
- # examples fail).
45
- t.fail_on_error = true
46
-
47
- # A message to print to stderr when there are failures.
48
- t.failure_message = nil
49
-
50
- # Use verbose output. If this is set to true, the task will print the
51
- # executed spec command to stdout.
52
- t.verbose = true
53
-
54
- # Use rcov for code coverage?
55
- t.rcov = false
56
-
57
- # Path to rcov.
58
- t.rcov_path = "rcov"
59
-
60
- # Command line options to pass to rcov. See 'rcov --help' about this
61
- t.rcov_opts = []
62
-
63
- # Command line options to pass to ruby. See 'ruby --help' about this
64
- t.ruby_opts = []
65
-
66
- # Path to rspec
67
- t.rspec_path = "rspec"
68
-
69
- # Command line options to pass to rspec. See 'rspec --help' about this
70
- t.rspec_opts = ["--color", "--backtrace"]
71
- end
72
- rescue LoadError => ex
73
- task :spec_test do
74
- abort 'rspec is not available. In order to run spec, you must: gem install rspec'
75
- end
76
- ensure
77
- task :spec => [:spec_test]
78
- task :test => [:spec_test]
79
- end
data/tasks/unit_test.rake DELETED
@@ -1,77 +0,0 @@
1
- # Installs a rake task for for running unit tests.
2
- #
3
- # This file installs the 'rake unit_test' and extends 'rake test' to run unit
4
- # tests, if any. It is automatically generated by Noe from your .noespec file,
5
- # and should therefore be configured there, under the variables/rake_tasks/unit_test
6
- # entry, as illustrated below:
7
- #
8
- # variables:
9
- # rake_tasks:
10
- # unit_test:
11
- # pattern: test/test*.rb
12
- # verbose: false
13
- # warning: false
14
- # ...
15
- #
16
- # If you have specific needs requiring manual intervention on this file,
17
- # don't forget to set safe-override to false in your noe specification:
18
- #
19
- # template-info:
20
- # manifest:
21
- # tasks/unit_test.rake:
22
- # safe-override: false
23
- #
24
- # More info about the TestTask and its options can be found on
25
- # http://rake.rubyforge.org/classes/Rake/TestTask.html
26
- #
27
- begin
28
- require 'rake/testtask'
29
- desc "Run unit tests"
30
- Rake::TestTask.new(:unit_test) do |t|
31
-
32
- # List of directories to added to $LOAD_PATH before running the
33
- # tests. (default is 'lib')
34
- t.libs = ["lib"]
35
-
36
- # True if verbose test output desired. (default is false)
37
- t.verbose = false
38
-
39
- # Test options passed to the test suite. An explicit TESTOPTS=opts
40
- # on the command line will override this. (default is NONE)
41
- t.options = nil
42
-
43
- # Request that the tests be run with the warning flag set.
44
- # E.g. warning=true implies "ruby -w" used to run the tests.
45
- t.warning = false
46
-
47
- # Glob pattern to match test files. (default is 'test/test*.rb')
48
- t.pattern = "test/test*.rb"
49
-
50
- # Style of test loader to use. Options are:
51
- #
52
- # * :rake -- Rake provided test loading script (default).
53
- # * :testrb -- Ruby provided test loading script.
54
- # * :direct -- Load tests using command line loader.
55
- #
56
- t.loader = :rake
57
-
58
- # Array of commandline options to pass to ruby when running test
59
- # loader.
60
- t.ruby_opts = []
61
-
62
- # Explicitly define the list of test files to be included in a
63
- # test. +list+ is expected to be an array of file names (a
64
- # FileList is acceptable). If both +pattern+ and +test_files+ are
65
- # used, then the list of test files is the union of the two.
66
- t.test_files = nil
67
-
68
- end
69
- rescue LoadError => ex
70
- task :unit_test do
71
- abort 'rspec is not available. In order to run spec, you must: gem install rspec'
72
- end
73
- ensure
74
- desc "Run all tests"
75
- task :test => [:unit_test]
76
- end
77
-
data/tasks/yard.rake DELETED
@@ -1,51 +0,0 @@
1
- # Installs a rake task to generate API documentation using yard.
2
- #
3
- # This file installs the 'rake yard' task. It is automatically generated by Noe from
4
- # your .noespec file, and should therefore be configured there, under the
5
- # variables/rake_tasks/yard entry, as illustrated below:
6
- #
7
- # variables:
8
- # rake_tasks:
9
- # yard:
10
- # files: lib/**/*.rb
11
- # options: []
12
- # ...
13
- #
14
- # If you have specific needs requiring manual intervention on this file,
15
- # don't forget to set safe-override to false in your noe specification:
16
- #
17
- # template-info:
18
- # manifest:
19
- # tasks/yard.rake:
20
- # safe-override: false
21
- #
22
- # This file has been written to conform to yard v0.6.4. More information about
23
- # yard and the rake task installed below can be found on http://yardoc.org/
24
- #
25
- begin
26
- require "yard"
27
- desc "Generate yard documentation"
28
- YARD::Rake::YardocTask.new(:yard) do |t|
29
- # Array of options passed to yardoc commandline. See 'yardoc --help' about this
30
- t.options = ["--output-dir", "doc/api", "-", "README.md", "CHANGELOG.md", "LICENCE.md"]
31
-
32
- # Array of ruby source files (and any extra documentation files
33
- # separated by '-')
34
- t.files = ["lib/**/*.rb"]
35
-
36
- # A proc to call before running the task
37
- # t.before = proc{ }
38
-
39
- # A proc to call after running the task
40
- # r.after = proc{ }
41
-
42
- # An optional lambda to run against all objects being generated.
43
- # Any object that the lambda returns false for will be excluded
44
- # from documentation.
45
- # t.verifier = lambda{|obj| true}
46
- end
47
- rescue LoadError
48
- task :yard do
49
- abort 'yard is not available. In order to run yard, you must: gem install yard'
50
- end
51
- end
@@ -1,16 +0,0 @@
1
- require 'stamina/stamina_test'
2
- require 'stamina/abbadingo'
3
- module Stamina
4
- module Abbadingo
5
- class RandomDFATest < StaminaTest
6
-
7
- def test_it_looks_ok_with_default_options
8
- dfa = RandomDFA.new(32).execute
9
- assert dfa.deterministic?
10
- assert dfa.minimal?
11
- assert dfa.complete?
12
- end
13
-
14
- end # class RandomDFATest
15
- end # module Abbadingo
16
- end # module Stamina
@@ -1,78 +0,0 @@
1
- require 'stamina/stamina_test'
2
- require 'stamina/abbadingo'
3
- module Stamina
4
- module Abbadingo
5
- class RandomSampleTest < StaminaTest
6
-
7
- def test_length_for
8
- rs = RandomSample::StringEnumerator.new
9
- assert_equal 0, rs.length_for(1)
10
- assert_equal 1, rs.length_for(2)
11
- assert_equal 1, rs.length_for(3)
12
- assert_equal 2, rs.length_for(4)
13
- assert_equal 2, rs.length_for(5)
14
- assert_equal 2, rs.length_for(6)
15
- assert_equal 2, rs.length_for(7)
16
- assert_equal 3, rs.length_for(8)
17
- end
18
-
19
- def test_string_for
20
- rs = RandomSample::StringEnumerator.new
21
- assert_equal [], rs.string_for(1)
22
- assert_equal ["0"], rs.string_for(2)
23
- assert_equal ["1"], rs.string_for(3)
24
- assert_equal ["0", "0"], rs.string_for(4)
25
- assert_equal ["1", "0"], rs.string_for(5)
26
- assert_equal ["0", "1"], rs.string_for(6)
27
- assert_equal ["1", "1"], rs.string_for(7)
28
- end
29
-
30
- def test_string_for_generates_all_diff
31
- rs = RandomSample::StringEnumerator.new
32
- h = {}
33
- (1..100).each{|i| h[rs.string_for(i)] = true}
34
- assert_equal 100, h.size
35
- end
36
-
37
- def test_string_for_respects_distribution
38
- rs = RandomSample::StringEnumerator.new
39
- lengths = Hash.new{|h,k| h[k] = 0}
40
- (1..127).each{|i| lengths[rs.string_for(i).size] += 1}
41
- assert_equal [0, 1, 2, 3, 4, 5, 6], lengths.keys.sort
42
- prop = (0..6).collect{|i| lengths[i].to_f/128}
43
- assert_equal [0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5], prop
44
- end
45
-
46
- def test_enumerator
47
- enum = RandomSample::StringEnumerator.new(10)
48
- lengths = Hash.new{|h,k| h[k] = 0}
49
- 20000.times{lengths[enum.one.size] += 1}
50
- assert (lengths.keys.sort - (0..10).to_a).empty?
51
- prop = (0..10).collect{|i| lengths[i].to_f/20000}
52
- assert((prop[-1] >= 0.45) && (prop[-1] <= 0.55))
53
- assert((prop[-2] >= 0.2) && (prop[-2] <= 0.3))
54
- assert((prop[-3] >= 0.1) && (prop[-3] <= 0.15))
55
- end
56
-
57
- def test_it_can_be_used_on_small_dfas
58
- dfa = RandomDFA.new(16).execute
59
- training, test = RandomSample.execute(dfa)
60
-
61
- assert test.size > 0
62
- assert training.size > 0
63
-
64
- # check training sample
65
- assert training.positive_count > 0
66
- assert training.negative_count > 0
67
- assert dfa.correctly_classify?(training)
68
-
69
- # check test sample
70
- assert test.positive_count > 0
71
- assert test.negative_count > 0
72
- assert dfa.correctly_classify?(test)
73
- end
74
-
75
-
76
- end # class RandomDFATest
77
- end # module Abbadingo
78
- end # module Stamina
@@ -1,516 +0,0 @@
1
- require 'test/unit'
2
- require 'stamina'
3
- module Stamina
4
-
5
- # Tests ADL parser
6
- class ADLTest < Test::Unit::TestCase
7
-
8
- # Tests ADL#parse on a valid dfa
9
- def test_can_parse_valid_empty_dfa
10
- fa = ADL::parse_automaton <<-AUTOMATON
11
- 1 0
12
- 0 true false
13
- AUTOMATON
14
- assert_equal(1, fa.state_count)
15
- assert_equal(0, fa.edge_count)
16
- assert_equal(true, fa.states[0].initial?)
17
- assert_equal(false, fa.states[0].accepting?)
18
- assert_equal(true, fa.deterministic?)
19
- assert_equal(false, fa.accepts?('+'))
20
- assert_equal(false, fa.accepts?('+ a'))
21
- end
22
-
23
- # Tests ADL#parse on a valid dfa
24
- def test_can_parse_valid_small_dfa
25
- fa = ADL::parse_automaton <<-AUTOMATON
26
- 3 4
27
- 0 true false
28
- 1 false false
29
- 2 false true
30
- 0 1 a
31
- 1 2 b
32
- 2 2 a
33
- 2 1 b
34
- AUTOMATON
35
- assert_equal(3, fa.state_count)
36
- assert_equal(4, fa.edge_count)
37
- fa.each_state {|s| assert_equal(s.index==0, s.initial?)}
38
- fa.each_state {|s| assert_equal(s.index==2, s.accepting?)}
39
- assert_equal(false, fa.accepts?('+'))
40
- assert_equal(false, fa.accepts?('+ a'))
41
- assert_equal(true, fa.accepts?('+ a b'))
42
- assert_equal(true, fa.accepts?('+ a b a'))
43
- assert_equal(false, fa.accepts?('+ a b a b'))
44
- assert_equal(true, fa.accepts?('+ a b a a a'))
45
- assert_equal(true, fa.accepts?('+ a b a a a b b a'))
46
- assert_equal(true, fa.accepts?('+ a b a a a b b a a a'))
47
- assert_equal(true, fa.accepts?('+ a b a a a b b a a a b b a'))
48
- end
49
-
50
- # Tests that ADL#parse detects a missing state
51
- def test_detect_missing_header
52
- assert_raise(ADL::ParseError) do
53
- ADL::parse_automaton <<-AUTOMATON
54
- 0 true false
55
- 1 false false
56
- 0 1 a
57
- 1 2 b
58
- 2 2 a
59
- 2 1 b
60
- AUTOMATON
61
- end
62
- assert_raise(ADL::ParseError) do
63
- ADL::parse_automaton <<-AUTOMATON
64
- # 3 4
65
- 0 true false
66
- 1 false false
67
- 0 1 a
68
- 1 2 b
69
- 2 2 a
70
- 2 1 b
71
- AUTOMATON
72
- end
73
- end
74
-
75
- # Tests that ADL#parse detects a missing state
76
- def test_detect_missing_state
77
- assert_raise(ADL::ParseError) do
78
- ADL::parse_automaton <<-AUTOMATON
79
- 3 4
80
- 0 true false
81
- 1 false false
82
- AUTOMATON
83
- end
84
- assert_raise(ADL::ParseError) do
85
- ADL::parse_automaton <<-AUTOMATON
86
- 3 4
87
- 0 true false
88
- 1 false false
89
- 0 1 a
90
- 1 2 b
91
- 2 2 a
92
- 2 1 b
93
- AUTOMATON
94
- end
95
- assert_raise(ADL::ParseError) do
96
- ADL::parse_automaton <<-AUTOMATON
97
- 3 4
98
- 0 true false
99
- 1 false false
100
- # 2 false true
101
- 0 1 a
102
- 1 2 b
103
- 2 2 a
104
- 2 1 b
105
- AUTOMATON
106
- end
107
- end
108
-
109
- # Tests that ADL#parse detects a missing edge
110
- def test_detect_missing_edge
111
- assert_raise(ADL::ParseError) do
112
- ADL::parse_automaton <<-AUTOMATON
113
- 3 4
114
- 0 true false
115
- 1 false false
116
- 2 false true
117
- 0 1 a
118
- 2 2 a
119
- 2 1 b
120
- AUTOMATON
121
- end
122
- assert_raise(ADL::ParseError) do
123
- ADL::parse_automaton <<-AUTOMATON
124
- 3 4
125
- 0 true false
126
- 1 false false
127
- 2 false true
128
- 0 1 a
129
- 1 2 b
130
- 2 2 a
131
- # 2 1 b
132
- AUTOMATON
133
- end
134
- end
135
-
136
- # Tests that ADL#parse detects a missing edge
137
- def test_detect_trailing_data
138
- assert_raise(ADL::ParseError) do
139
- fa = ADL::parse_automaton <<-AUTOMATON
140
- 1 0
141
- 0 true false
142
- trailing here
143
- AUTOMATON
144
- end
145
- end
146
-
147
- # Tests that ADL#parse detects a missing edge
148
- def test_allows_comments_and_white_lines
149
- fa = nil
150
- assert_nothing_raised(ADL::ParseError) do
151
- fa = ADL::parse_automaton <<-AUTOMATON
152
-
153
- # a header is always allowed,
154
- # with empty lines as well
155
- #
156
- 3 4
157
-
158
- # state definitions may be introduced...
159
- 0 true false
160
- 1 false false
161
- # and perturbated
162
- 2 false true
163
- 0 1 a
164
-
165
- # edge introduction may be misplaced
166
- 1 2 b
167
- 2 2 a
168
-
169
- 2 1 b
170
-
171
- # and end of file may contain documentation as well
172
- # as empty lines:
173
-
174
- AUTOMATON
175
- end
176
- assert_equal(3, fa.state_count)
177
- assert_equal(4, fa.edge_count)
178
- fa.each_state {|s| assert_equal(s.index==0, s.initial?)}
179
- fa.each_state {|s| assert_equal(s.index==2, s.accepting?)}
180
- assert_equal(false, fa.accepts?('+'))
181
- assert_equal(false, fa.accepts?('+ a'))
182
- assert_equal(true, fa.accepts?('+ a b'))
183
- assert_equal(true, fa.accepts?('+ a b a'))
184
- assert_equal(false, fa.accepts?('+ a b a b'))
185
- assert_equal(true, fa.accepts?('+ a b a a a'))
186
- assert_equal(true, fa.accepts?('+ a b a a a b b a'))
187
- assert_equal(true, fa.accepts?('+ a b a a a b b a a a'))
188
- assert_equal(true, fa.accepts?('+ a b a a a b b a a a b b a'))
189
- end
190
-
191
- # Tests ADL::parse on the documentation example
192
- def test_valid_adl_automaton_example
193
- fa = nil
194
- assert_nothing_raised(ADL::ParseError) do
195
- here = File.dirname(__FILE__)
196
- automaton_adl = File.join(here, '..', '..', 'example', 'adl', 'automaton.adl')
197
- fa = ADL::parse_automaton_file(automaton_adl)
198
- end # assert_nothing_raised
199
- assert_equal(5, fa.state_count)
200
- assert_equal(6, fa.edge_count)
201
- assert_equal(true, fa.parses?('? hello w o r l d'))
202
- assert_equal(false, fa.accepts?('? hello w o r l d'))
203
- assert_equal(true, fa.rejects?('? hello w o r l d'))
204
- assert_equal(true, fa.accepts?('? hello'))
205
- assert_equal(false, fa.accepts?('? hello w'))
206
- assert_equal(true, fa.accepts?('? hello w o'))
207
- assert_equal(false, fa.accepts?('? hello w o r'))
208
- assert_equal(false, fa.accepts?('? hello w o r l'))
209
- end
210
-
211
- # Tests ADL::parse on the documentation succint example
212
- def test_valid_adl_automaton_succint_example
213
- fa = nil
214
- assert_nothing_raised do
215
- fa = ADL::parse_automaton <<-AUTOMATON
216
- # Some header comments: tool which has generated this automaton,
217
- # maybe a date or other tool options ...
218
- # here: 'this automaton accepts the a(ba)* regular language'
219
- 2 2
220
- 0 true false
221
- 1 false true
222
- 0 1 a
223
- 1 0 b
224
- AUTOMATON
225
- end
226
- assert_equal(2, fa.state_count)
227
- assert_equal(2, fa.edge_count)
228
- assert_equal(true, fa.accepts?('? a'))
229
- assert_equal(true, fa.accepts?('? a b a'))
230
- assert_equal(true, fa.accepts?('? a b a b a'))
231
- assert_equal(false, fa.accepts?('?'))
232
- assert_equal(false, fa.accepts?('? a b'))
233
- assert_equal(false, fa.accepts?('? a b a b'))
234
- end
235
-
236
- # Checks that an initial state may arruve lately
237
- def test_parse_automaton_allows_late_initial_state
238
- fa = nil
239
- assert_nothing_raised do
240
- fa = ADL::parse_automaton <<-AUTOMATON
241
- # Some header comments: tool which has generated this automaton,
242
- # maybe a date or other tool options ...
243
- # here: 'this automaton accepts the a(ba)* regular language'
244
- 2 2
245
- 0 false false
246
- 1 true true
247
- 0 1 a
248
- 1 0 b
249
- AUTOMATON
250
- end
251
- end
252
-
253
- # Tests parse_automaton on an automated randomly generated using jail
254
- def test_parse_automaton_on_jail_randdfa
255
- fa = nil
256
- assert_nothing_raised do
257
- fa = ADL::parse_automaton_file(File.join(File.dirname(__FILE__),'randdfa.adl'))
258
- end
259
- end
260
-
261
- # Tests an important security issue about parse_automaton
262
- def test_parse_automaton_does_not_executes_ruby_code
263
- begin
264
- assert_raise ADL::ParseError do
265
- ADL::parse_automaton <<-AUTOMATON
266
- Kernel.exit(-1)
267
- AUTOMATON
268
- end
269
- rescue SystemExit
270
- assert false, 'SECURITY issue: ADL::parse_automaton executes ruby code'
271
- end
272
- begin
273
- assert_raise ADL::ParseError do
274
- ADL::parse_automaton_file(File.dirname(__FILE__)+'/exit.rb')
275
- end
276
- rescue SystemExit
277
- assert false, 'SECURITY issue: ADL::parse_automaton executes ruby code'
278
- end
279
- end
280
-
281
- # Tests ADL::parse_string
282
- def test_parse_string
283
- s = ADL::parse_string('?')
284
- assert_equal(true, InputString===s)
285
- assert_equal(false, s.positive?)
286
- assert_equal(false, s.negative?)
287
- assert_equal(true, s.unlabeled?)
288
- assert_equal(nil, s.label)
289
- assert_equal(true, s.empty?)
290
- assert_equal([], s.symbols)
291
-
292
- s = ADL::parse_string('+')
293
- assert_equal(true, InputString===s)
294
- assert_equal(true, s.positive?)
295
- assert_equal(true, s.label)
296
- assert_equal(true, s.empty?)
297
- assert_equal([], s.symbols)
298
-
299
- s = ADL::parse_string('-')
300
- assert_equal(true, InputString===s)
301
- assert_equal(false, s.positive?)
302
- assert_equal(false, s.label)
303
- assert_equal(true, s.empty?)
304
- assert_equal([], s.symbols)
305
-
306
- s = ADL::parse_string('? a')
307
- assert_equal(['a'], s.symbols)
308
- assert_equal(false, s.positive?)
309
- assert_equal(false, s.negative?)
310
- assert_equal(true, s.unlabeled?)
311
- assert_equal(nil, s.label)
312
- assert_equal(['a'], s.symbols)
313
-
314
- s = ADL::parse_string('+ a')
315
- assert_equal(['a'], s.symbols)
316
- assert_equal(true, s.positive?)
317
-
318
- s = ADL::parse_string('- a')
319
- assert_equal(['a'], s.symbols)
320
- assert_equal(false, s.positive?)
321
-
322
- s = ADL::parse_string('+ a b a b ')
323
- assert_equal(['a','b','a','b'], s.symbols)
324
- assert_equal(true, s.positive?)
325
-
326
- s = ADL::parse_string('- a b a c')
327
- assert_equal(['a','b','a','c'], s.symbols)
328
- assert_equal(false, s.positive?)
329
- end
330
-
331
- # Tests ADL::parse_sample
332
- def test_parse_sample
333
- sample = ADL::parse_sample <<-SAMPLE
334
- + a b a b a b
335
- # this is a comment, next is an empty line
336
- +
337
- + a b
338
- - a a
339
- ? a b
340
- # trailing comment allowed
341
- SAMPLE
342
- assert sample==Sample['+ a b a b a b', '+ a b', '- a a', '+', '? a b']
343
- end
344
-
345
- # Tests that ADL::parse_sample accepts the empty sample
346
- def test_parse_sample_accepts_empty_sample
347
- samples = [
348
- ADL::parse_sample(""),
349
- ADL::parse_sample("#"),
350
- ADL::parse_sample(<<-SAMPLE
351
- SAMPLE
352
- ),
353
- ADL::parse_sample(<<-SAMPLE
354
-
355
- # this is a comment, between two empty lines
356
-
357
- SAMPLE
358
- )
359
- ]
360
- samples.each do |sample|
361
- assert sample==Sample.new
362
- end
363
- end
364
-
365
- # Tests that ADL::parse_sample accepts empty strings
366
- def test_parse_sample_accepts_empty_strings
367
- assert Sample['+'] == ADL::parse_sample('+')
368
- assert Sample['-'] == ADL::parse_sample('-')
369
- assert Sample['+'] == ADL::parse_sample(<<-SAMPLE
370
- +
371
- SAMPLE
372
- )
373
- assert Sample['-'] == ADL::parse_sample(<<-SAMPLE
374
- -
375
- SAMPLE
376
- )
377
- end
378
-
379
- # Tests validity of sample.adl file
380
- def test_valid_adl_sample_example
381
- here = File.dirname(__FILE__)
382
- sample_adl = File.join(here, '..', '..', 'example', 'adl', 'sample.adl')
383
- sample = ADL::parse_sample_file(sample_adl)
384
- expected = Sample.new
385
- expected << InputString.new(['a', 'b', 'a', 'b'], true)
386
- expected << InputString.new(['a', 'a'], false)
387
- expected << InputString.new(['a', 'b'], nil)
388
- expected << InputString.new([], true)
389
- expected << InputString.new(['hello', 'world'], true)
390
- expected << InputString.new(['h','e','l','l','o','w','o','r','l','d'], true)
391
- expected << InputString.new(['helloworld'], true)
392
- expected << InputString.new(['a','+','b','-','a','-','b','+a'], true)
393
- expected << InputString.new(['#','a','#','b','a','b','#','and','all','these','words','are','symbols', 'too', '!!'],true)
394
- expected.each do |s|
395
- assert sample.include?(s), "|#{s}| from expected is included in sample"
396
- end
397
- sample.each do |s|
398
- assert expected.include?(s), "|#{s}| from sample is included in expected"
399
- end
400
- assert expected == sample
401
- end
402
-
403
- # Tests validity of sample.adl file
404
- def test_valid_adl_sample_succint_example
405
- sample = ADL::parse_sample <<-SAMPLE
406
- # Some header comments: tool which has generated this sample,
407
- # maybe a date or other tool options ...
408
- # here: 'this sample is caracteristic for the a(ba)* regular language'
409
- -
410
- + a
411
- - a b
412
- + a b a
413
- SAMPLE
414
- expected = Sample.new
415
- expected << InputString.new([], false)
416
- expected << InputString.new(['a'], true)
417
- expected << InputString.new(['a','b'], false)
418
- expected << InputString.new(['a','b','a'], true)
419
- assert expected==sample
420
- end
421
-
422
- # Tests an important security issue about parse_automaton
423
- def test_parse_sample_does_not_executes_ruby_code
424
- begin
425
- ADL::parse_sample <<-AUTOMATON
426
- + Kernel.exit(-1)
427
- AUTOMATON
428
- rescue SystemExit
429
- assert false, 'SECURITY issue: ADL::parse_automaton executes ruby code'
430
- end
431
- begin
432
- ADL::parse_sample_file(File.dirname(__FILE__)+'/exit.rb')
433
- rescue SystemExit
434
- assert false, 'SECURITY issue: ADL::parse_automaton executes ruby code'
435
- end
436
- end
437
-
438
- # tests that state IDs are loaded and can be used.
439
- def test_state_names
440
- fa = ADL::parse_automaton <<-AUTOMATON
441
- 3 4
442
- A true false
443
- B false false
444
- C false true
445
- A B a
446
- B C b
447
- C C a
448
- C B b
449
- AUTOMATON
450
-
451
- ['A','B','C'].each do |statename|
452
- assert_equal statename,fa.get_state(statename)[:name]
453
- end
454
-
455
- assert_equal true,fa.get_state('A').initial?
456
- assert_equal false,fa.get_state('B').initial?
457
- assert_equal false,fa.get_state('C').initial?
458
-
459
- assert_equal false,fa.get_state('A').accepting?
460
- assert_equal false,fa.get_state('B').accepting?
461
- assert_equal true,fa.get_state('C').accepting?
462
- end
463
-
464
- def test_parsing_recognizes_failures
465
- assert_raise Stamina::ADL::ParseError do
466
- fa = ADL::parse_sample <<-EOF
467
- 3 4
468
- A true false
469
- B false false
470
- C false true
471
- A B a
472
- B C b
473
- C C a
474
- C B b
475
- EOF
476
- end
477
- assert_raise Stamina::ADL::ParseError do
478
- sample = ADL::parse_automaton <<-EOF
479
- + a b a b a b
480
- # this is a comment, next is an empty line
481
- +
482
- + a b
483
- - a a
484
- a b
485
- # trailing comment allowed
486
- EOF
487
- end
488
- end
489
-
490
- def test_allows_error_states
491
- dfa = ADL::parse_automaton <<-EOF
492
- 5 0
493
- 0 true true true
494
- 1 false false true
495
- 2 false false false
496
- 3 false true false
497
- 4 false true
498
- EOF
499
- assert dfa.ith_state(0).accepting? && dfa.ith_state(0).error?
500
- assert !dfa.ith_state(1).accepting? && dfa.ith_state(1).error?
501
- assert !dfa.ith_state(2).accepting? && !dfa.ith_state(2).error?
502
- assert dfa.ith_state(3).accepting? && !dfa.ith_state(3).error?
503
- assert !dfa.ith_state(4).error?
504
- end
505
-
506
- def test_flushes_error_states
507
- dfa = ADL::parse_automaton <<-EOF
508
- 2 0
509
- 0 true false
510
- 1 false false true
511
- EOF
512
- assert_equal "1 false false true", dfa.to_adl.split("\n")[2].strip
513
- end
514
-
515
- end # class ADLTest
516
- end # module Stamina