Skip to content

Instantly share code, notes, and snippets.

@DNNX

DNNX/Spec.hs Secret

Created December 24, 2016 19:58
Show Gist options
  • Save DNNX/2a08a74bb1a55f850f456ec3a94bafa6 to your computer and use it in GitHub Desktop.
Save DNNX/2a08a74bb1a55f850f456ec3a94bafa6 to your computer and use it in GitHub Desktop.
#! /bin/ruby
require 'active_support/core_ext/integer/time'
require 'active_support/time_with_zone'
def parse_gets
$stdin.gets.chomp.split(';')
end
def check(args = ARGV)
lhs, rhs = split(args)
lhs = parse(lhs)
rhs = parse(rhs)
t = ActiveSupport::TimeZone.us_zones[-2].parse('Fri, 23 Dec 2016 18:30:02 EST -05:00')
lres = apply(t, lhs)
rres = apply(t, rhs)
lres == rres
end
def split(args)
idx = args.index(',')
[args[0...idx], args[idx+1..-1]]
end
def parse(args)
args.map { |x| parse_one(x) }
end
def parse_one(arg)
_, unit, amount = arg.split
Integer(amount).public_send(unit.downcase)
end
def apply(t, deltas)
deltas.reduce(t) { |acc, delta| delta.since(acc) }
end
loop do
args = parse_gets
$stdout.puts check(args)
$stdout.flush
end
import Test.Framework (defaultMain, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck
import Test.QuickCheck.Monadic
import Data.List
import Data.Function
import System.Process
import System.IO
main :: IO ()
main = do
let createProcess = (shell "ruby check_dates.rb"){std_in = CreatePipe, std_out = CreatePipe}
withCreateProcess createProcess $ \(Just stdin) (Just stdout) _ _ ->
quickCheckWith stdArgs {maxSuccess = 100000, maxSize=100500} (prop_checkActiveSupport2 stdin stdout)
data TimeUnit
= Seconds
| Minutes
| Hours
| Days
| Weeks
| Months
| Years deriving (Eq, Show, Ord)
data Operation = Add TimeUnit Int deriving (Eq, Ord)
instance Show Operation where
show (Add unit amount) = "Add " ++ show unit ++ " " ++ show amount
timeUnit :: Operation -> TimeUnit
timeUnit (Add unit _) = unit
amount :: Operation -> Int
amount (Add _ amount) = amount
instance Arbitrary TimeUnit where
arbitrary = oneof
[ pure Seconds
, pure Minutes
, pure Hours
-- , pure Days
-- , pure Weeks
-- , pure Months
-- , pure Years
]
instance Arbitrary Operation where
arbitrary = Add <$> arbitrary <*> arbitrary
squash :: [Operation] -> [Operation]
squash ops = map f $ groupBy ((==) `on` timeUnit) $ sort ops
where
f :: [Operation] -> Operation
f ops = Add (timeUnit $ head ops) (sum $ map amount ops)
checkActiveSupport :: [Operation] -> [Operation] -> Handle -> Handle -> IO Bool
checkActiveSupport ops1 ops2 stdin stdout = do
hPutStrLn stdin (intercalate ";" (map show ops1 ++ [","] ++ map show ops2))
hFlush stdin
raw <- hGetLine stdout
return (raw == "true")
prop_checkActiveSupport :: Handle -> Handle -> [Operation] -> Property
prop_checkActiveSupport stdin stdout ops = monadicIO $ do
passed <- run (checkActiveSupport ops (squash ops) stdin stdout)
assert passed
prop_checkActiveSupport2 :: Handle -> Handle -> Operation -> Operation -> Property
prop_checkActiveSupport2 stdin stdout op1 op2 = monadicIO $ do
passed <- run (checkActiveSupport [op1, op2] [op2, op1] stdin stdout)
assert passed
prop_checkActiveSupport3 :: Handle -> Handle -> Operation -> Property
prop_checkActiveSupport3 stdin stdout op = monadicIO $ do
let neg (Add unit amount) = Add unit (-amount)
passed <- run (checkActiveSupport [op, neg op] [] stdin stdout)
assert passed
prop_checkActiveSupport4 :: Handle -> Handle -> Int -> Operation -> Property
prop_checkActiveSupport4 stdin stdout d op = monadicIO $ do
let neg (Add unit amount) = Add unit (-amount)
passed <- run (checkActiveSupport [Add Seconds d, op, neg op] [Add Seconds d] stdin stdout)
assert passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment