dither 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8544177ee83d6cbef836448d4e0d550cff9affc5
4
- data.tar.gz: 91019ef4fc9f4cdaada74fddf41e4a9b4007f41a
3
+ metadata.gz: 1615f95c32d97e471ea43d8714dee5a9c9e4f1ad
4
+ data.tar.gz: 2284c90542966f2487969b68d35c30d372493a6c
5
5
  SHA512:
6
- metadata.gz: 0aa18ecaf1bf5e84690ef817f5b3b2607389359b9d6233af3beb7a74d3e79c3768d43b982766390b346be8430b3dd9334295a644f4004b750422fc7271a07eed
7
- data.tar.gz: 192d58cfe5c72c8a1c177791a406779583084732d9f276cca1b3c4607d5c189901de369c80dc8fc4ebbf89cc65227df16d3ab184d6082318fea4aaa4829745ca
6
+ metadata.gz: 9f548f30dc8de6d28276fe42284451f01408bd1b86c4e627bd7f40651e62a2cddc872940007b840cf2653dfafeb3d92597726a587f2210e31f9be1cf7eb975d8
7
+ data.tar.gz: 5c8fb0bb33f372328275e2090821ffdfa8bba20dd7c20e054ae696acecffa114fb2b3416faceeb3985c971418c3269e394ee2f56b271fcc3f660b02fb2001ee0
data/Gemfile.lock CHANGED
@@ -1,13 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dither (0.0.4)
4
+ dither (0.0.5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ coveralls (0.7.1)
10
+ multi_json (~> 1.3)
11
+ rest-client
12
+ simplecov (>= 0.7)
13
+ term-ansicolor
14
+ thor
9
15
  diff-lcs (1.2.5)
16
+ docile (1.1.5)
17
+ mime-types (2.3)
18
+ multi_json (1.10.1)
19
+ netrc (0.7.7)
10
20
  rake (0.9.6)
21
+ rest-client (1.7.2)
22
+ mime-types (>= 1.16, < 3.0)
23
+ netrc (~> 0.7)
11
24
  rspec (3.2.0)
12
25
  rspec-core (~> 3.2.0)
13
26
  rspec-expectations (~> 3.2.0)
@@ -21,11 +34,21 @@ GEM
21
34
  diff-lcs (>= 1.2.0, < 2.0)
22
35
  rspec-support (~> 3.2.0)
23
36
  rspec-support (3.2.2)
37
+ simplecov (0.9.0)
38
+ docile (~> 1.1.0)
39
+ multi_json
40
+ simplecov-html (~> 0.8.0)
41
+ simplecov-html (0.8.0)
42
+ term-ansicolor (1.3.0)
43
+ tins (~> 1.0)
44
+ thor (0.19.1)
45
+ tins (1.3.3)
24
46
 
25
47
  PLATFORMS
26
48
  ruby
27
49
 
28
50
  DEPENDENCIES
51
+ coveralls
29
52
  dither!
30
53
  rake (~> 0.9.2)
31
54
  rspec (~> 3.2)
data/dither.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.add_development_dependency "rspec", "~> 3.2"
18
18
  s.add_development_dependency "rake", "~> 0.9.2"
19
+ s.add_development_dependency "coveralls"
19
20
 
20
21
  s.files = `git ls-files`.split("\n")
21
22
  s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
data/lib/dither/ipog.rb CHANGED
@@ -2,72 +2,7 @@
2
2
 
3
3
  module Dither
4
4
  class IPOG
5
- attr_reader :params, :t, :constraints, :test_set, :orig_params, :unbound_param_pool
6
- private :params, :t, :constraints, :test_set, :orig_params
7
-
8
- def initialize(params, t, opts = {})
9
- init_params(params)
10
- @t = t
11
- unless opts[:constraints].nil?
12
- @constraints = opts[:constraints].map(&:to_a)
13
- .map { |a| a.map { |b| @params[@map_to_orig_index.key(b[0])][b[1]] } }
14
- .map(&:to_set)
15
- end
16
-
17
- raise 't must be >= 2' if t < 2
18
- raise 't must be <= params.length' if t > params.length
19
- params.each do |param|
20
- raise 'param length must be > 1' if param.length < 2
21
- end
22
- end
23
-
24
- def init_params(user_params)
25
- tmp = []
26
- user_params.each_with_index { |e, i| tmp << [i, e] }
27
- @orig_params = tmp.sort_by { |a| a[1].length }
28
- .reverse!
29
-
30
- @map_to_orig_index = {}
31
- @orig_params.each_with_index do |e, i|
32
- @map_to_orig_index[i] = e[0]
33
- end
34
-
35
- @params = []
36
- @unbound_param_pool = []
37
- orig_params.each_with_index do |e, i|
38
- @params << (0...e[1].length).map { |j| Param.new(i, j) }
39
- @unbound_param_pool << UnboundParam.new(i)
40
- end
41
- params
42
- end
43
-
44
- # return nil if unable to satisfy constraints
45
- def maximize_coverage(i, test_case, pi)
46
- current_max = 0
47
- current_max_j = 0
48
- current_matches = []
49
-
50
- (0...params[i].length).each do |j|
51
- current_param = params[i][j]
52
- test_case << current_param
53
- unless violates_constraints?(test_case)
54
- matches = pi.select { |a| a.subset?(test_case) }
55
- count = matches.count
56
-
57
- if count > current_max
58
- current_max = count
59
- current_max_j = j
60
- current_matches = matches
61
- end
62
- end
63
- test_case.delete(current_param)
64
- end
65
-
66
- test_case << params[i][current_max_j]
67
- return nil if violates_constraints?(test_case)
68
-
69
- current_matches
70
- end
5
+ include IPOGHelper
71
6
 
72
7
  def run
73
8
  # add into test set a test for each combination of values
@@ -94,7 +29,7 @@ module Dither
94
29
 
95
30
  # vertical extension for parameter i
96
31
  pi.each do |a|
97
- if test_set.any? { |test_case| a.subset?(test_case) }
32
+ if test_set.any? { |b| a.subset?(b) }
98
33
  pi.delete(a)
99
34
  else
100
35
 
@@ -114,85 +49,10 @@ module Dither
114
49
  end
115
50
  end
116
51
 
117
- test_set.map { |a| fill_unbound(a) }
52
+ @test_set = test_set.map { |a| fill_unbound(a) }
118
53
  .delete_if(&:nil?)
119
54
  .to_a
55
+ @test_set
120
56
  end
121
-
122
- def violates_constraints?(params)
123
- return false if constraints.nil?
124
- constraints.any? { |b| b.subset?(params) }
125
- end
126
-
127
- def comb
128
- ranges = (0...t).to_a.inject([]) do |a, i|
129
- a << (0...params[i].length).map { |j| params[i][j] }
130
- end
131
-
132
- products = ranges[1..-1].inject(ranges[0]) do |a, b|
133
- a = a.product(b)
134
- end
135
-
136
- products.map(&:flatten)
137
- .map { |a| TestCase.create(params, unbound_param_pool, a) }
138
- end
139
-
140
- def comb_i(param_i)
141
- values = (0...param_i).to_a.combination((t-1)).to_a
142
- values.each do |a|
143
- a << param_i
144
- end
145
- result = []
146
- values.each do |a|
147
- result += a[1..-1]
148
- .inject((0...params[a[0]].length).map { |b| params[0][b] }) { |p, i| p.product((0...params[i].length).to_a.map { |b| params[i][b] }) }
149
- .map(&:flatten)
150
- .map { |a| TestCase.create(params, unbound_param_pool, a) }
151
- end
152
- result
153
- end
154
-
155
- private
156
-
157
- def fill_unbound(data)
158
- arr = Array.new(params.length)
159
- data.each do |param|
160
- unless param.unbound?
161
- orig_param = orig_params[param.i]
162
- arr[orig_param[0]] = orig_param[1][param.j]
163
- end
164
- end
165
-
166
- arr.each_with_index do |e, i|
167
- if e.nil?
168
- j = 0
169
- orig_param = orig_params.find { |a| a[0] = i }
170
- arr[i] = orig_param[1][j]
171
- end
172
- end
173
-
174
- return nil if violates_constraints?(data)
175
- arr
176
- end
177
-
178
- def find_unbound(param_array, stuff)
179
- data = {}
180
- stuff.each do |param|
181
- data[param.i] = param.j
182
- end
183
-
184
- unbound = []
185
- param_array.each do |param|
186
- case data[param.i]
187
- when param.j
188
- when nil
189
- unbound << param
190
- else
191
- unbound = nil
192
- break
193
- end
194
- end
195
- unbound
196
- end
197
- end
198
- end
57
+ end # IPOG
58
+ end # Dither
@@ -0,0 +1,140 @@
1
+ # coding: utf-8
2
+
3
+ module Dither
4
+ module IPOGHelper
5
+ attr_reader :params, :t, :constraints, :test_set, :orig_params, :unbound_param_pool
6
+ private :params, :t, :constraints, :test_set, :orig_params, :unbound_param_pool
7
+
8
+ def initialize(params, t, opts = {})
9
+ init_params(params)
10
+ @t = t
11
+ unless opts[:constraints].nil?
12
+ @constraints = opts[:constraints].map(&:to_a)
13
+ .map { |a| a.map { |b| @params[@map_to_orig_index.key(b[0])][b[1]] } }
14
+ .map(&:to_set)
15
+ end
16
+
17
+ raise 't must be >= 2' if t < 2
18
+ raise 't must be <= params.length' if t > params.length
19
+ params.each do |param|
20
+ raise 'param length must be > 1' if param.length < 2
21
+ end
22
+ end
23
+
24
+ def init_params(user_params)
25
+ tmp = []
26
+ @input_params = user_params
27
+ user_params.each_with_index { |e, i| tmp << [i, e] }
28
+ @orig_params = tmp.sort_by { |a| a[1].length }
29
+ .reverse!
30
+
31
+ @map_to_orig_index = {}
32
+ @orig_params.each_with_index do |e, i|
33
+ @map_to_orig_index[i] = e[0]
34
+ end
35
+
36
+ @params = []
37
+ @unbound_param_pool = []
38
+ orig_params.each_with_index do |e, i|
39
+ @params << (0...e[1].length).map { |j| Param.new(i, j) }
40
+ @unbound_param_pool << UnboundParam.new(i)
41
+ end
42
+ params
43
+ end
44
+
45
+ # return nil if unable to satisfy constraints
46
+ def maximize_coverage(i, test_case, pi)
47
+ current_max = 0
48
+ current_max_j = 0
49
+ current_matches = []
50
+
51
+ (0...params[i].length).each do |j|
52
+ current_param = params[i][j]
53
+ test_case << current_param
54
+ unless violates_constraints?(test_case)
55
+ matches = pi.select { |a| a.subset?(test_case) }
56
+ count = matches.count
57
+
58
+ if count > current_max
59
+ current_max = count
60
+ current_max_j = j
61
+ current_matches = matches
62
+ end
63
+ end
64
+ test_case.delete(current_param)
65
+ end
66
+
67
+ test_case << params[i][current_max_j]
68
+ return nil if violates_constraints?(test_case)
69
+
70
+ current_matches
71
+ end
72
+
73
+ def violates_constraints?(params)
74
+ return false if constraints.nil?
75
+ constraints.any? { |b| b.subset?(params) }
76
+ end
77
+
78
+ private
79
+
80
+ def comb
81
+ ranges = (0...t).to_a.inject([]) do |a, i|
82
+ a << (0...params[i].length).map { |j| params[i][j] }
83
+ end
84
+
85
+ products = ranges[1..-1].inject(ranges[0]) do |a, b|
86
+ a = a.product(b)
87
+ end
88
+
89
+ result = products.map(&:flatten)
90
+ .map { |a| TestCase.create(params, unbound_param_pool, a) }
91
+ result
92
+ end
93
+
94
+ def comb_i(param_i)
95
+ values = (0...param_i).to_a.combination((t-1)).to_a
96
+ values.each do |a|
97
+ a << param_i
98
+ end
99
+ result = []
100
+ values.each do |a|
101
+ result += a[1..-1]
102
+ .inject((0...params[a[0]].length).map { |b| params[a[0]][b] }) { |p, i| p.product((0...params[i].length).to_a.map { |c| params[i][c] }) }
103
+ .map(&:flatten)
104
+ .map { |a| TestCase.create(params, unbound_param_pool, a) }
105
+ end
106
+ result
107
+ end
108
+
109
+
110
+ def fill_unbound(data)
111
+ arr = Array.new(params.length)
112
+ data.each do |param|
113
+ unless param.unbound?
114
+ i = @map_to_orig_index[param.i]
115
+ arr[i] = @input_params[i][param.j]
116
+ end
117
+ end
118
+
119
+ arr.each_with_index do |e, i|
120
+ next unless e.nil?
121
+
122
+ orig_param = @input_params[i]
123
+ (0...orig_param.length).each do |j|
124
+ data << params[@map_to_orig_index.key(i)][j]
125
+ if violates_constraints?(data)
126
+ data.delete(params[@map_to_orig_index.key(i)][j])
127
+ next
128
+ else
129
+ arr[i] = orig_param[j]
130
+ end
131
+ end
132
+ return nil if arr[i].nil?
133
+ end
134
+
135
+ return nil if violates_constraints?(data)
136
+
137
+ arr
138
+ end
139
+ end # IPOGHelper
140
+ end # Dither
@@ -0,0 +1,85 @@
1
+ # coding: utf-8
2
+
3
+ module Dither
4
+ class MIPOG
5
+ include Dither::IPOGHelper
6
+
7
+ def maximize_unbound_coverage(i, test_case, pi)
8
+ all_unbound = test_case.unbound
9
+ .map { |a| a.create_params(params[a.i].length) }
10
+ .flatten
11
+
12
+ current_max = 0
13
+ current_max_j = 0
14
+ current_outer_param = all_unbound[0]
15
+ current_matches = []
16
+
17
+ all_unbound.each do |outer_param|
18
+ test_case << outer_param
19
+
20
+ (0...params[i].length).each do |j|
21
+ current_param = params[i][j]
22
+ test_case << current_param
23
+ count = pi.count { |a| a.subset?(test_case) }
24
+
25
+ if count > current_max
26
+ current_max = count
27
+ current_max_j = j
28
+ current_outer_param = outer_param
29
+ end
30
+ test_case.delete(current_param)
31
+ end
32
+ test_case.delete(outer_param)
33
+ end
34
+
35
+ test_case << params[i][current_max_j]
36
+ test_case << current_outer_param
37
+ test_case.delete(unbound_param_pool[current_outer_param.i])
38
+
39
+ current_matches
40
+ end
41
+
42
+ def run
43
+ # add into test set a test for each combination of values
44
+ # of the first t parameter
45
+ test_set = comb
46
+
47
+ (t...params.length).each do |i|
48
+ # let pi
49
+ # be the set of t-way combinations of values involving
50
+ # parameter Pi and t -1 parameters among the first i – 1
51
+ # parameters
52
+ pi = comb_i(i)
53
+
54
+ # horizontal extension for parameter i
55
+ test_set.each do |test_case|
56
+ if !test_case.contains_unbound?
57
+ cover = maximize_coverage(i, test_case, pi)
58
+ else
59
+ cover = maximize_unbound_coverage(i, test_case, pi)
60
+ end
61
+
62
+ # remove covered combinations
63
+ pi -= cover
64
+ end
65
+
66
+ # vertical extension for parameter i
67
+ until pi.empty?
68
+ pi.sort!
69
+ test_case, coverage = maximize_vertical_coverage(i, pi[0].dup, pi)
70
+ test_set << test_case.create_unbound(i)
71
+ pi -= coverage
72
+ end
73
+ end
74
+ test_set.map { |a| fill_unbound(a) }
75
+ end
76
+
77
+ def maximize_vertical_coverage(i, test_case, pi)
78
+ coverage = [pi[0]]
79
+ pi[1..-1].each do |a|
80
+ coverage << a unless test_case.merge_without_conflict(i, a).nil?
81
+ end
82
+ [test_case, coverage]
83
+ end
84
+ end # MIPOG
85
+ end # Dither
@@ -80,7 +80,9 @@ module Dither
80
80
  new_elements.each { |a| new_self << a }
81
81
 
82
82
  return nil if block_given? && block.call(new_self)
83
- new_self
83
+
84
+ new_elements.each { |a| self << a }
85
+ self
84
86
  end
85
87
  end # TestCase
86
88
  end # Dither
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Dither
3
- VERSION = '0.0.5'
3
+ VERSION = '0.0.6'
4
4
  end
data/lib/dither.rb CHANGED
@@ -6,9 +6,15 @@ module Dither
6
6
  def self.all_pairs(params, t = 2, opts = {})
7
7
  IPOG.new(params, t, opts).run
8
8
  end
9
+
10
+ def self.mipog(params, t = 2, opts = {})
11
+ MIPOG.new(params, t, opts).run
12
+ end
9
13
  end # Dither
10
14
 
11
15
  require 'dither/param'
12
16
  require 'dither/unbound_param'
13
17
  require 'dither/test_case'
18
+ require 'dither/ipog_helper'
14
19
  require 'dither/ipog'
20
+ require 'dither/mipog'
@@ -19,14 +19,62 @@ describe Dither do
19
19
  expect(Dither.all_pairs(params)).to eq([[:a, :d, :h],
20
20
  [:a, :e, :i],
21
21
  [:a, :f, :h],
22
- [:b, :d, :h],
23
- [:b, :e, :i],
24
- [:b, :f, :h],
22
+ [:b, :d, :i],
23
+ [:b, :e, :h],
24
+ [:b, :f, :i],
25
25
  [:c, :d, :h],
26
26
  [:c, :e, :i],
27
27
  [:c, :f, :h]])
28
28
  end
29
29
 
30
+ it 'can compute 3-way mipog' do
31
+ params = [(0...2).to_a, (0...2).to_a, (0..3).to_a]
32
+ expect(Dither.mipog(params, 3)).to eq([[0, 0, 0],
33
+ [1, 0, 0],
34
+ [0, 1, 0],
35
+ [1, 1, 0],
36
+ [0, 0, 1],
37
+ [1, 0, 1],
38
+ [0, 1, 1],
39
+ [1, 1, 1],
40
+ [0, 0, 2],
41
+ [1, 0, 2],
42
+ [0, 1, 2],
43
+ [1, 1, 2],
44
+ [0, 0, 3],
45
+ [1, 0, 3],
46
+ [0, 1, 3],
47
+ [1, 1, 3],
48
+ ])
49
+ end
50
+
51
+ it 'can compute 2-way mipog using symbols' do
52
+ params = [[:a, :b, :c], [:d, :e, :f], [:h, :i]]
53
+ expect(Dither.mipog(params)).to eq([[:a, :d, :h],
54
+ [:a, :e, :i],
55
+ [:a, :f, :h],
56
+ [:b, :d, :i],
57
+ [:b, :e, :h],
58
+ [:b, :f, :i],
59
+ [:c, :d, :h],
60
+ [:c, :e, :i],
61
+ [:c, :f, :h]])
62
+ end
63
+
64
+ it 'can compute 2-way mipog' do
65
+ params = [(0...2).to_a, (0..3).to_a]
66
+ expect(Dither.mipog(params)).to eq([
67
+ [0, 0],
68
+ [1, 0],
69
+ [0, 1],
70
+ [1, 1],
71
+ [0, 2],
72
+ [1, 2],
73
+ [0, 3],
74
+ [1, 3],
75
+ ])
76
+ end
77
+
30
78
  it 'can compute 2-way ipog' do
31
79
  params = [(0...2).to_a, (0..3).to_a]
32
80
  expect(Dither.all_pairs(params)).to eq([
@@ -91,8 +139,6 @@ describe Dither do
91
139
  params = [(0...2).to_a, (0...2).to_a, (0...2).to_a, (0..3).to_a]
92
140
  expect(Dither.all_pairs(params, 3,
93
141
  :constraints => [
94
- {0 => 0,
95
- 2 => 2},
96
142
  {0 => 0,
97
143
  1 => 1,
98
144
  2 => 0}
@@ -100,10 +146,10 @@ describe Dither do
100
146
  [1, 1, 0, 0],
101
147
  [1, 0, 1, 0],
102
148
  [0, 1, 1, 0],
103
- [0, 0, 0, 1],
149
+ [1, 0, 0, 1],
104
150
  [1, 1, 0, 1],
105
- [1, 0, 1, 1],
106
- [0, 1, 1, 1],
151
+ [0, 0, 1, 1],
152
+ [1, 1, 1, 1],
107
153
  [0, 0, 0, 2],
108
154
  [1, 1, 0, 2],
109
155
  [1, 0, 1, 2],
@@ -112,32 +158,6 @@ describe Dither do
112
158
  [1, 1, 0, 3],
113
159
  [1, 0, 1, 3],
114
160
  [0, 1, 1, 3],
115
- ])
116
- results = Dither.all_pairs([
117
- (0...10).to_a,
118
- (0...10).to_a,
119
- (0...4).to_a,
120
- (0...3).to_a,
121
- (0...3).to_a,
122
- (0...2).to_a,
123
- (0...2).to_a,
124
- (0...2).to_a,
125
- (0...2).to_a,
126
- (0...2).to_a,
127
- (0...2).to_a,
128
- (0...2).to_a,
129
- ], 3)
130
-
131
- # results = Dither.all_pairs([
132
- # (0...2).to_a,
133
- # (0...2).to_a,
134
- # (0...2).to_a,
135
- # (0...3).to_a,
136
- # ], 3)
137
- require 'csv'
138
- results.each { |a| puts a.to_csv }
139
- puts results.count
140
-
141
-
161
+ [0, 0, 0, 1]])
142
162
  end
143
163
  end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,5 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
1
4
  $LOAD_PATH.unshift File.expand_path("../lib")
2
5
  require 'dither'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dither
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Gowan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-19 00:00:00.000000000 Z
11
+ date: 2015-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.9.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: coveralls
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Efficient test generation strategies
42
56
  email:
43
57
  - gowanjason@gmail.com
@@ -56,6 +70,8 @@ files:
56
70
  - dither.gemspec
57
71
  - lib/dither.rb
58
72
  - lib/dither/ipog.rb
73
+ - lib/dither/ipog_helper.rb
74
+ - lib/dither/mipog.rb
59
75
  - lib/dither/param.rb
60
76
  - lib/dither/test_case.rb
61
77
  - lib/dither/unbound_param.rb