Make generated Haskell code an instance of Arbitrary
----------------------------------------------------

                 Key: THRIFT-728
                 URL: https://issues.apache.org/jira/browse/THRIFT-728
             Project: Thrift
          Issue Type: New Feature
          Components: Compiler (Haskell), Library (Haskell)
         Environment: All
            Reporter: Aran Donohue
            Priority: Minor
         Attachments: arbitrary.patch

The patch
   * Generates Arbitrary instances for Thrift structs, enums and exceptions
   * Provides Arbitrary instances for GHC's Int64, Data.Map.Map and Data.Set.Set
   * Makes Thrift enums instances of Bounded and improves the Enum instance 
declaration

Making a type an instance of Test.QuickCheck.Arbitrary specifies how to 
generate random instances of the struct. This is useful for testing.

For example, consider the following simple Thrift declaration:

{code:title=distributed_log.thrift}
enum LogLevel { DEBUG, INFO, WARNING, ERROR }                                   
      
                                                                                
      
typedef i32 UnixTimeStamp                                                       
      
                                                                                
      
struct LogEntry {                                                               
      
   1: LogLevel level,                                                           
      
   2: UnixTimeStamp timestamp,                                                  
      
   3: string message                                                            
      
}                                                                               
      
                                                                                
      
service Logger {                                                                
      
   void log(1: LogEntry entry)                                                  
      
}
{code}

With the patch, the following program (import statements elided) is a fuzzer 
for the log service.

{code:title=LogTest.hs}
-- ripped from Test.QuickCheck.Gen.sample'                                      
      
infexamples ∷  Gen a →  IO [a]                                                  
      
infexamples (MkGen m) =                                                         
      
  do rnd ←  newStdGen                                                           
      
     let rnds rnd = rnd1 : rnds rnd2 where (rnd1, rnd2) = split rnd             
      
     return [(m r n) | (r, n) ←  rnds rnd `zip` [0,2..] ]                       
      
                                                                                
      
infentries = infexamples (arbitrary ∷  Gen LogEntry)                            
      
                                                                                
      
main = do entries ←  infentries                                                 
      
          forM entries logAnEntry                                               
      
                                                                                
      
logAnEntry entry = do                                                           
      
    transport ←  hOpen ("localhost", PortNumber 9090)                           
      
    let binProto = BinaryProtocol transport                                     
      
    let client = (binProto, binProto)                                           
      
    (Client.log client) entry                                                   
      
    tClose transport                                                            
      
    `Control.Exception.catch`                                                   
      
    (λ(TransportExn s t) →  print s)
--On systems with Haskell we could just generate a fuzzer like this one.
{code}

In implementing the Arbitrary instances, it was useful to make Thrift enums 
instances of Bounded and to improve the Enum instance. Specifically, whereas 
before, 

{code}
[DEBUG .. ]
{code}

would throw an exception, now it behaves as expected without an exception.

I consider the patch incomplete. It's more of a starting point for a discussion 
at this point than a serious candidate for inclusion. If it is of interest, I'd 
appreciate some direction on testing it as well as style, and I'd welcome any 
other comments or thoughts.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to