ocg 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/LICENSE +21 -0
- data/README.md +167 -0
- data/lib/ocg.rb +5 -0
- data/lib/ocg/error.rb +9 -0
- data/lib/ocg/main.rb +41 -0
- data/lib/ocg/operator/abstract.rb +44 -0
- data/lib/ocg/operator/and.rb +44 -0
- data/lib/ocg/operator/mix.rb +50 -0
- data/lib/ocg/operator/or.rb +43 -0
- data/lib/ocg/options.rb +77 -0
- data/lib/ocg/validation.rb +18 -0
- data/lib/ocg/version.rb +6 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e9901f2790c6f74257fc4a081df5bbacefb6084fcbd5f1e31c5bf1cd5e69b7f
|
4
|
+
data.tar.gz: 602a5952e6ece5235fd19b469113903cf4a3750043aa35fdfe5091cb865d4903
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 683e94067c89e54ffa979c682d40ef6739c8c3a4d92be87a6250cde5c6981498dde7dc42adddb1f78561303954b4344ca7642b15693c616920e6313f589fcb85
|
7
|
+
data.tar.gz: 10a4f52d299916f8237ccdfa65258a261d1b49811700fc7d73813575a36547aafed3d4ae96686445cc63936b88db90cc3eae7547da335c1589984df9da82fc30
|
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Andrew Aladjev
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 AUTHORS
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
# Option combination generator
|
2
|
+
|
3
|
+
[![Travis test status](https://travis-ci.org/andrew-aladev/ocg.svg?branch=master)](https://travis-ci.org/andrew-aladev/ocg)
|
4
|
+
[![AppVeyor test status](https://ci.appveyor.com/api/projects/status/github/andrew-aladev/ocg?branch=master&svg=true)](https://ci.appveyor.com/project/andrew-aladev/ocg/branch/master)
|
5
|
+
[![Cirrus test status](https://api.cirrus-ci.com/github/andrew-aladev/ocg.svg?branch=master)](https://cirrus-ci.com/github/andrew-aladev/ocg)
|
6
|
+
[![Circle test status](https://circleci.com/gh/andrew-aladev/ocg/tree/master.svg?style=shield)](https://circleci.com/gh/andrew-aladev/ocg/tree/master)
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
```sh
|
11
|
+
gem install ocg
|
12
|
+
```
|
13
|
+
|
14
|
+
You can build it from source.
|
15
|
+
|
16
|
+
```sh
|
17
|
+
rake gem
|
18
|
+
gem install pkg/ocg-*.gem
|
19
|
+
```
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require "ocg"
|
25
|
+
|
26
|
+
generator = OCG.new(
|
27
|
+
:a => %w[a b],
|
28
|
+
:b => 1..2
|
29
|
+
)
|
30
|
+
.or(
|
31
|
+
:c => %i[c d],
|
32
|
+
:d => 3..4
|
33
|
+
)
|
34
|
+
.and(
|
35
|
+
:e => %w[e f],
|
36
|
+
:f => 5..6
|
37
|
+
)
|
38
|
+
.mix(
|
39
|
+
:g => %i[g h],
|
40
|
+
:h => 7..8
|
41
|
+
)
|
42
|
+
|
43
|
+
until generator.finished?
|
44
|
+
pp generator.next
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
It will populate all option combinations.
|
49
|
+
|
50
|
+
## Docs
|
51
|
+
|
52
|
+
Options should be prepared in the following form:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
{
|
56
|
+
option_name => option_values,
|
57
|
+
...
|
58
|
+
}
|
59
|
+
```
|
60
|
+
|
61
|
+
Options hash should not be empty.
|
62
|
+
`option_name` can be any valid hash key.
|
63
|
+
`option_values` should be convertable to array using `to_a`.
|
64
|
+
`option_values` should not be empty.
|
65
|
+
|
66
|
+
`OCG.new options` will prepare a generator.
|
67
|
+
It will provide all possible option combinations.
|
68
|
+
|
69
|
+
You can combine generators using `and`, `mix` and `or`.
|
70
|
+
|
71
|
+
`and` method will provide all combinations between generators.
|
72
|
+
`mix` method will merge right generator combinations into left without combining. `mix` guarantees that both left and right generator combinations will be provided at least once.
|
73
|
+
`or` method will concat generator combinations without merging.
|
74
|
+
|
75
|
+
`reset` method allows to receive combinations once again.
|
76
|
+
|
77
|
+
`next` method returns next combination.
|
78
|
+
|
79
|
+
`last` method returns last combination.
|
80
|
+
|
81
|
+
`started?` method returns true when at least one combination was generated.
|
82
|
+
|
83
|
+
`finished?` method returns true when all combination were generated.
|
84
|
+
|
85
|
+
`length` returns combinations length.
|
86
|
+
|
87
|
+
## Why?
|
88
|
+
|
89
|
+
Many software uses multiple options and have complex relations between them.
|
90
|
+
We want to test this software.
|
91
|
+
We need to provide optimal option combination to maximize test coverage.
|
92
|
+
|
93
|
+
Let's look at [zstd compressor options](http://facebook.github.io/zstd/zstd_manual.html#Chapter5).
|
94
|
+
|
95
|
+
`compressionLevel` option is a preset for `windowLog`, `hashLog`, etc options.
|
96
|
+
We may set `compressionLevel` or other options, mixing is pointless.
|
97
|
+
We can say that there are 2 option groups: group with single `compressionLevel` option and group with other options.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
general_generator = OCG.new(
|
101
|
+
:compressionLevel => -10..10
|
102
|
+
)
|
103
|
+
.or(
|
104
|
+
:windowLog => 0..10,
|
105
|
+
:hashLog => 0..10,
|
106
|
+
...
|
107
|
+
)
|
108
|
+
```
|
109
|
+
|
110
|
+
`enableLongDistanceMatching` option enables usage of `ldmHashLog`, `ldmMinMatch`, etc options.
|
111
|
+
We may use `:enableLongDistanceMatching => false` or `:enableLongDistanceMatching => true` with other options.
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
ldm_generator = OCG.new(
|
115
|
+
:enableLongDistanceMatching => [false]
|
116
|
+
)
|
117
|
+
.or(
|
118
|
+
:enableLongDistanceMatching => [true],
|
119
|
+
:ldmHashLog => 0..10,
|
120
|
+
:ldmMinMatch => 0..10,
|
121
|
+
...
|
122
|
+
)
|
123
|
+
```
|
124
|
+
|
125
|
+
General compression and long distance matching option groups correlate between each other.
|
126
|
+
We want to have all possible combinations between these option groups.
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
main_generator = general_generator.and ldm_generator
|
130
|
+
```
|
131
|
+
|
132
|
+
`contentSizeFlag`, `checksumFlag`, `dictIDFlag` options are additional options.
|
133
|
+
These options don't correlate between each other or with main options.
|
134
|
+
We want just to mix their values with main options.
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
almost_complete_generator = main_generator.mix(
|
138
|
+
:contentSizeFlag => [true, false]
|
139
|
+
)
|
140
|
+
.mix(
|
141
|
+
:checksumFlag => [true, false]
|
142
|
+
)
|
143
|
+
.mix(
|
144
|
+
:dictIDFlag => [true, false]
|
145
|
+
)
|
146
|
+
```
|
147
|
+
|
148
|
+
`nbWorkers`, `jobSize` and `overlapLog` options are thread related options.
|
149
|
+
These options correlate between each other but don't correlate with main options.
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
complete_generator = almost_complete_generator.mix(
|
153
|
+
:nbWorkers => 0..2,
|
154
|
+
:jobSize => 1..10,
|
155
|
+
:overlapLog => 0..9
|
156
|
+
)
|
157
|
+
```
|
158
|
+
|
159
|
+
## CI
|
160
|
+
|
161
|
+
Travis and Appveyor CI uses [scripts/toolchains.sh](scripts/toolchains.sh) directly.
|
162
|
+
Cirrus and Circle CI uses prebuilt [scripts/test-images](scripts/test-images).
|
163
|
+
Cirrus CI uses amd64 image, Circle CI - i686.
|
164
|
+
|
165
|
+
## License
|
166
|
+
|
167
|
+
MIT license, see LICENSE and AUTHORS.
|
data/lib/ocg.rb
ADDED
data/lib/ocg/error.rb
ADDED
data/lib/ocg/main.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Option combination generator.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require "forwardable"
|
5
|
+
|
6
|
+
require_relative "error"
|
7
|
+
require_relative "options"
|
8
|
+
|
9
|
+
class OCG
|
10
|
+
extend ::Forwardable
|
11
|
+
|
12
|
+
DELEGATORS = %i[reset next last started? finished? length].freeze
|
13
|
+
|
14
|
+
def initialize(generator_or_options)
|
15
|
+
@generator = self.class.prepare_generator generator_or_options
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.prepare_generator(generator_or_options)
|
19
|
+
return generator_or_options if generator_or_options.is_a? OCG
|
20
|
+
|
21
|
+
Options.new generator_or_options
|
22
|
+
end
|
23
|
+
|
24
|
+
def_delegators :@generator, *DELEGATORS
|
25
|
+
|
26
|
+
def and(generator_or_options)
|
27
|
+
Operator::AND.new self, generator_or_options
|
28
|
+
end
|
29
|
+
|
30
|
+
def mix(generator_or_options)
|
31
|
+
Operator::MIX.new self, generator_or_options
|
32
|
+
end
|
33
|
+
|
34
|
+
def or(generator_or_options)
|
35
|
+
Operator::OR.new self, generator_or_options
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
require_relative "operator/and"
|
40
|
+
require_relative "operator/mix"
|
41
|
+
require_relative "operator/or"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Option combination generator.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require_relative "../error"
|
5
|
+
|
6
|
+
class OCG
|
7
|
+
module Operator
|
8
|
+
class Abstract < OCG
|
9
|
+
def initialize(left_generator_or_options, right_generator_or_options)
|
10
|
+
@left_generator = OCG.prepare_generator left_generator_or_options
|
11
|
+
@right_generator = OCG.prepare_generator right_generator_or_options
|
12
|
+
|
13
|
+
reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
@left_generator.reset
|
18
|
+
@right_generator.reset
|
19
|
+
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def next
|
24
|
+
raise NotImplementedError, "\"next\" is not implemented"
|
25
|
+
end
|
26
|
+
|
27
|
+
def last
|
28
|
+
raise NotImplementedError, "\"last\" is not implemented"
|
29
|
+
end
|
30
|
+
|
31
|
+
def started?
|
32
|
+
raise NotImplementedError, "\"started?\" is not implemented"
|
33
|
+
end
|
34
|
+
|
35
|
+
def finished?
|
36
|
+
raise NotImplementedError, "\"finished?\" is not implemented"
|
37
|
+
end
|
38
|
+
|
39
|
+
def length
|
40
|
+
raise NotImplementedError, "\"length\" is not implemented"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Option combination generator.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require_relative "abstract"
|
5
|
+
|
6
|
+
class OCG
|
7
|
+
module Operator
|
8
|
+
class AND < Abstract
|
9
|
+
def next
|
10
|
+
return nil if finished?
|
11
|
+
|
12
|
+
if @right_generator.finished?
|
13
|
+
@right_generator.reset
|
14
|
+
@left_generator.next.merge @right_generator.next
|
15
|
+
else
|
16
|
+
left_last = @left_generator.last
|
17
|
+
left_last = @left_generator.next if left_last.nil?
|
18
|
+
left_last.merge @right_generator.next
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def last
|
23
|
+
left_last = @left_generator.last
|
24
|
+
right_last = @right_generator.last
|
25
|
+
|
26
|
+
return nil if left_last.nil? || right_last.nil?
|
27
|
+
|
28
|
+
left_last.merge right_last
|
29
|
+
end
|
30
|
+
|
31
|
+
def started?
|
32
|
+
@left_generator.started? || @right_generator.started?
|
33
|
+
end
|
34
|
+
|
35
|
+
def finished?
|
36
|
+
@left_generator.finished? && @right_generator.finished?
|
37
|
+
end
|
38
|
+
|
39
|
+
def length
|
40
|
+
@left_generator.length * @right_generator.length
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Option combination generator.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require_relative "abstract"
|
5
|
+
|
6
|
+
class OCG
|
7
|
+
module Operator
|
8
|
+
class MIX < Abstract
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
|
12
|
+
@main_generator = \
|
13
|
+
if @right_generator.length > @left_generator.length
|
14
|
+
@right_generator
|
15
|
+
else
|
16
|
+
@left_generator
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def next
|
21
|
+
return nil if finished?
|
22
|
+
|
23
|
+
@left_generator.reset if @left_generator.finished?
|
24
|
+
@right_generator.reset if @right_generator.finished?
|
25
|
+
@left_generator.next.merge @right_generator.next
|
26
|
+
end
|
27
|
+
|
28
|
+
def last
|
29
|
+
left_last = @left_generator.last
|
30
|
+
right_last = @right_generator.last
|
31
|
+
|
32
|
+
return nil if left_last.nil? || right_last.nil?
|
33
|
+
|
34
|
+
left_last.merge right_last
|
35
|
+
end
|
36
|
+
|
37
|
+
def started?
|
38
|
+
@main_generator.started?
|
39
|
+
end
|
40
|
+
|
41
|
+
def finished?
|
42
|
+
@main_generator.finished?
|
43
|
+
end
|
44
|
+
|
45
|
+
def length
|
46
|
+
@main_generator.length
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Option combination generator.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require_relative "abstract"
|
5
|
+
|
6
|
+
class OCG
|
7
|
+
module Operator
|
8
|
+
class OR < Abstract
|
9
|
+
def next
|
10
|
+
return nil if finished?
|
11
|
+
|
12
|
+
if @left_generator.finished?
|
13
|
+
@right_generator.next
|
14
|
+
else
|
15
|
+
@left_generator.next
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def last
|
20
|
+
left_last = @left_generator.last
|
21
|
+
right_last = @right_generator.last
|
22
|
+
|
23
|
+
if right_last.nil?
|
24
|
+
left_last
|
25
|
+
else
|
26
|
+
right_last
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def started?
|
31
|
+
@left_generator.started? || @right_generator.started?
|
32
|
+
end
|
33
|
+
|
34
|
+
def finished?
|
35
|
+
@left_generator.finished? && @right_generator.finished?
|
36
|
+
end
|
37
|
+
|
38
|
+
def length
|
39
|
+
@left_generator.length + @right_generator.length
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/ocg/options.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Option combination generator.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require_relative "validation"
|
5
|
+
|
6
|
+
class OCG
|
7
|
+
class Options
|
8
|
+
def initialize(options)
|
9
|
+
Validation.validate_options options
|
10
|
+
@options = Hash[options.map { |name, values| [name, values.to_a] }]
|
11
|
+
|
12
|
+
# End to start is more traditional way of making combinations.
|
13
|
+
@keys = @options.keys.reverse
|
14
|
+
|
15
|
+
@last_options = nil
|
16
|
+
|
17
|
+
reset_value_indexes
|
18
|
+
|
19
|
+
@is_finished = false
|
20
|
+
end
|
21
|
+
|
22
|
+
protected def reset_value_indexes
|
23
|
+
@value_indexes = Hash[@options.map { |name, _values| [name, 0] }]
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset
|
27
|
+
return nil unless started?
|
28
|
+
|
29
|
+
@last_options = nil
|
30
|
+
|
31
|
+
# If state is finished than all value indexes are already zero.
|
32
|
+
reset_value_indexes unless @is_finished
|
33
|
+
|
34
|
+
@is_finished = false
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def next
|
40
|
+
return nil if @is_finished
|
41
|
+
|
42
|
+
@last_options = Hash[@value_indexes.map { |name, value_index| [name, @options[name][value_index]] }]
|
43
|
+
|
44
|
+
@is_finished = @keys.all? do |name|
|
45
|
+
values = @options[name]
|
46
|
+
new_value_index = @value_indexes[name] + 1
|
47
|
+
|
48
|
+
if new_value_index < values.length
|
49
|
+
@value_indexes[name] = new_value_index
|
50
|
+
next false
|
51
|
+
end
|
52
|
+
|
53
|
+
# Reset value index to zero.
|
54
|
+
@value_indexes[name] = 0
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
@last_options
|
59
|
+
end
|
60
|
+
|
61
|
+
def last
|
62
|
+
@last_options
|
63
|
+
end
|
64
|
+
|
65
|
+
def started?
|
66
|
+
!@last_options.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
def finished?
|
70
|
+
@is_finished
|
71
|
+
end
|
72
|
+
|
73
|
+
def length
|
74
|
+
@options.reduce(1) { |length, (_name, values)| length * values.length }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Option combination generator.
|
2
|
+
# Copyright (c) 2019 AUTHORS, MIT License.
|
3
|
+
|
4
|
+
require_relative "error"
|
5
|
+
|
6
|
+
class OCG
|
7
|
+
module Validation
|
8
|
+
def self.validate_options(options)
|
9
|
+
raise ValidateError, "invalid options hash" unless options.is_a? ::Hash
|
10
|
+
raise ValidateError, "options should not be empty" if options.empty?
|
11
|
+
|
12
|
+
options.each do |_name, values|
|
13
|
+
raise ValidateError, "option values should respond to \"to_a\"" unless values.respond_to? :to_a
|
14
|
+
raise ValidateError, "option values should not be empty" if values.to_a.empty?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/ocg/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ocg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Aladjev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.75'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.75'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop-performance
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.3'
|
69
|
+
description:
|
70
|
+
email: aladjev.andrew@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- AUTHORS
|
76
|
+
- LICENSE
|
77
|
+
- README.md
|
78
|
+
- lib/ocg.rb
|
79
|
+
- lib/ocg/error.rb
|
80
|
+
- lib/ocg/main.rb
|
81
|
+
- lib/ocg/operator/abstract.rb
|
82
|
+
- lib/ocg/operator/and.rb
|
83
|
+
- lib/ocg/operator/mix.rb
|
84
|
+
- lib/ocg/operator/or.rb
|
85
|
+
- lib/ocg/options.rb
|
86
|
+
- lib/ocg/validation.rb
|
87
|
+
- lib/ocg/version.rb
|
88
|
+
homepage: https://github.com/andrew-aladev/ocg
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata: {}
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubygems_version: 3.0.6
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: Option combination generator.
|
111
|
+
test_files: []
|