Created
April 2, 2014 13:26
-
-
Save dodecaphonic/9934064 to your computer and use it in GitHub Desktop.
Exploring QuickCheck in Ruby via Rantly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
source "https://rubygems.org" | |
gem "minitest" | |
gem "rantly", github: "hayeah/rantly" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "singleton" | |
class Nil | |
include Singleton | |
def empty?; true; end | |
def to_s | |
"Nil" | |
end | |
end | |
class Cons | |
def initialize(head, tail = Nil.instance) | |
@head = head | |
@tail = tail | |
end | |
attr_reader :head, :tail | |
def empty?; false; end | |
def to_s | |
"(#{head} . #{tail.to_s})" | |
end | |
end | |
module List | |
def self.reverse(list, acc = Nil.instance) # !> assigned but unused variable - total | |
if list.empty? | |
acc | |
else | |
reverse(list.tail, Cons.new(list.head, acc)) | |
end | |
end | |
def self.from_values(*values) | |
values.reverse.inject(Nil.instance) { |ls, v| Cons.new(v, ls) } | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "singleton" | |
class List | |
def to_s | |
raise "Don't use this directly, fool" | |
end | |
def empty?; true; end | |
def contains?(v); false; end | |
def prepend(v) | |
Cons.new(v, self) | |
end | |
def reverse(acc = Nil.instance) | |
if empty? | |
acc | |
else | |
tail.reverse(Cons.new(head, acc)) | |
end | |
end | |
def self.from_values(*values) | |
values.reverse.inject(Nil.instance) { |ls, v| Cons.new(v, ls) } | |
end | |
end | |
class Nil < List | |
include Singleton | |
def to_s | |
"Nil" | |
end | |
end | |
class Cons < List | |
def initialize(head, tail = Nil.instance) | |
@head = head | |
@tail = tail | |
end | |
attr_reader :head, :tail | |
def empty?; false; end | |
def contains?(v) | |
head == v || tail.contains?(v) | |
end | |
def to_s | |
"(#{head} . #{tail.to_s})" | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "minitest/autorun" | |
require_relative "minitest_extension" | |
require_relative "list2" | |
class ListTest < Minitest::Test | |
def test_reversing_lists | |
assert_equal "(3 . (2 . (1 . Nil)))", | |
List.from_values(1, 2, 3).reverse.to_s | |
assert_equal "(9 . (400 . (321 . (1 . (10 . Nil)))))", | |
List.from_values(10, 1, 321, 400, 9).reverse.to_s | |
assert_equal "Nil", Nil.instance.reverse.to_s | |
assert_equal "(1 . Nil)", List.from_values(1).reverse.to_s | |
end | |
def test_reversing_by_property | |
property { | |
length = range(0, 500) | |
List.from_values(array(length) { integer }) | |
}.check { |list| | |
assert_equal list.to_s, list.reverse.reverse.to_s | |
} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "minitest/autorun" | |
require_relative "minitest_extension" | |
require_relative "list" | |
class ListTest < Minitest::Test | |
def test_reversing_lists | |
assert_equal "(3 . (2 . (1 . Nil)))", | |
List.reverse(List.from_values(1, 2, 3)).to_s | |
assert_equal "(9 . (400 . (321 . (1 . (10 . Nil)))))", | |
List.reverse(List.from_values(10, 1, 321, 400, 9)).to_s | |
assert_equal "Nil", List.reverse(Nil.instance).to_s | |
assert_equal "(1 . Nil)", List.reverse(List.from_values(1)).to_s | |
end | |
def test_reversing_by_property | |
property { | |
length = range(0, 500) | |
List.from_values(array(length) { integer }) | |
}.check { |list| | |
assert_equal list.to_s, List.reverse(List.reverse(list)).to_s | |
} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "minitest" | |
require "rantly" | |
require "rantly/property" | |
class Minitest::Test | |
def property(&blk) | |
Rantly::Property.new(blk) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative "list2" | |
class DumbSet | |
def initialize(storage = Nil.instance) | |
@storage = storage | |
end | |
attr_reader :storage | |
private :storage | |
def push(v) | |
if !storage.contains?(v) | |
DumbSet.new(storage.prepend(v)) | |
else | |
self | |
end | |
end | |
alias_method :<<, :push | |
def contains?(v) | |
storage.contains?(v) | |
end | |
def delete(v) | |
ls = storage | |
tmp = DumbSet.new | |
while !ls.empty? | |
if (ls.head != v) | |
tmp = tmp << ls.head | |
end | |
ls = ls.tail | |
end | |
tmp | |
end | |
def to_a | |
values = [] | |
list = storage | |
until list.empty? | |
values << list.head | |
list = list.tail | |
end | |
values | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "minitest/autorun" | |
require_relative "minitest_extension" | |
require_relative "set" | |
class DumbSetTest < Minitest::Test | |
def setup | |
@s = (((DumbSet.new << 1) << 2) << 3) | |
end | |
attr_reader :s | |
def test_contains | |
assert s.contains?(3) | |
assert s.contains?(2) | |
assert s.contains?(1) | |
assert !s.contains?(4) | |
end | |
def test_uniqueness | |
assert_equal [-32, 1, 2, 3], (s << -32 << -32 << -32).to_a.sort | |
end | |
def test_contains_property | |
property { | |
array(range(0, 100)) { integer } | |
}.check { |vs| | |
s = vs.inject(DumbSet.new) { |ds, v| ds << v } | |
assert vs.all? { |v| s.contains?(v) } | |
} | |
end | |
def test_uniqueness_property | |
property { | |
array(range(0, 100)) { integer } | |
}.check { |vs| | |
ns = vs.inject(DumbSet.new) { |ds, v| ds << v } | |
rs = vs.inject(ns) { |ds, v| ds << v } | |
assert_equal vs.sort, ns.to_a.sort | |
} | |
end | |
def test_delete | |
os = DumbSet.new << 1 << 2 << 3 | |
ns = os.delete(1337) | |
assert_equal [1, 2, 3], ns.to_a.sort | |
ns = os.delete(3) | |
assert_equal [1, 2], ns.to_a.sort | |
ns = ns.delete(2) | |
assert_equal [1], ns.to_a.sort | |
ns = (ns << 432).delete(1) | |
assert_equal [432], ns.to_a.sort | |
ns = ns.delete(432) | |
assert_equal [], ns.to_a.sort | |
end | |
def test_delete_property | |
property { | |
array(10) { range(0, 5000) }.uniq | |
}.check { |values| | |
os = values.inject(DumbSet.new) { |s, v| s << v } | |
ds = values[0..1].inject(os) { |s, v| s.delete(v) } | |
assert_equal (values.size - 2), ds.to_a.size | |
} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment