lib/rantly/shrinks.rb in rantly-0.3.2 vs lib/rantly/shrinks.rb in rantly-1.0.0
- old
+ new
@@ -1,56 +1,173 @@
+# Integer : shrink to zero
class Integer
def shrink
- if self < 0 then (self / 2).floor + 1
- elsif self <= 10 && self > 0 then self - 1
- elsif self > 0 then ((self + 1) / 2).ceil - 1
+ shrunk = if self > 8
+ self / 2
+ elsif self > 0
+ self - 1
+ elsif self < -8
+ (self + 1) / 2
+ elsif self < 0
+ self + 1
else
- return 0
+ 0
end
+ return shrunk
end
+ def retry?
+ false
+ end
+
def shrinkable?
self != 0
end
end
+# String : shrink to ""
class String
def shrink
+ shrunk = self.dup
if self.size > 0
idx = Random::rand(self.size)
- shrunk = self.dup
shrunk[idx] = ""
- return shrunk
- else
- return ""
end
+ return shrunk
end
+ def retry?
+ false
+ end
+
def shrinkable?
self != ""
end
end
-class Array
+# Array where elements can be shrunk but not removed
+class Tuple
+ def initialize(a)
+ @array = a
+ @position = a.size - 1
+ end
+
+ def [](i)
+ @array[i]
+ end
+
+ def []=(i, value)
+ @array[i] = value
+ end
+
+ def length
+ @array.length
+ end
+
+ def size
+ self.length
+ end
+
+ def to_s
+ @array.to_s.insert(1, "T ")
+ end
+
+ def inspect
+ self.to_s
+ end
+
+ def each(&block)
+ @array.each(&block)
+ end
+
+ def array
+ return @array
+ end
+
def shrink
- idx = find_index{|e| e.respond_to?(:shrinkable?) && e.shrinkable?}
- if idx != nil
- clone = self.dup
- clone[idx] = clone[idx].shrink
- return clone
- elsif !self.empty?
- i = Random::rand(self.length)
- a2 = self.dup
- a2.delete_at(i)
- return a2
- else
- return self
+ shrunk = @array.dup
+ while @position >= 0
+ e = @array.at(@position)
+ if e.respond_to?(:shrinkable?) && e.shrinkable?
+ break
+ end
+ @position -= 1
end
+ if @position >= 0
+ shrunk[@position] = e.shrink
+ @position -= 1
+ end
+ return Tuple.new(shrunk)
end
+ def retry?
+ @position >= 0
+ end
+
def shrinkable?
- self.any?{|e| e.respond_to?(:shrinkable?) && e.shrinkable? } ||
- !self.empty?
+ @array.any? {|e| e.respond_to?(:shrinkable?) && e.shrinkable? }
+ end
+end
+
+# Array where the elements that can't be shrunk are removed
+class Deflating
+ def initialize(a)
+ @array = a
+ @position = a.size - 1
+ end
+
+ def [](i)
+ @array[i]
+ end
+
+ def []=(i, value)
+ @array[i] = value
+ end
+
+ def length
+ @array.length
+ end
+
+ def size
+ self.length
+ end
+
+ def to_s
+ @array.to_s.insert(1, "D ")
+ end
+
+ def inspect
+ self.to_s
+ end
+
+ def each(&block)
+ @array.each(&block)
+ end
+
+ def array
+ return @array
+ end
+
+ def shrink
+ shrunk = @array.dup
+ if @position >= 0
+ e = @array.at(@position)
+ if e.respond_to?(:shrinkable?) && e.shrinkable?
+ shrunk[@position] = e.shrink
+ else
+ shrunk.delete_at(@position)
+ end
+ @position -= 1
+ end
+ return Deflating.new(shrunk)
+ end
+
+ def retry?
+ @position >= 0
+ end
+
+ def shrinkable?
+ !@array.empty?
end
end
class Hash
def shrink