dither 0.0.5 → 0.0.6

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.
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