Thrift
  1. Thrift
  2. THRIFT-728

Make generated Haskell code an instance of Arbitrary

    Details

    • Type: New Feature New Feature
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Labels:
    • Environment:

      All

    • Patch Info:
      Patch Available

      Description

      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:

      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)                                                        
      }
      

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

      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.
      

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

      [DEBUG .. ]
      

      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.

      1. arbitrary.patch
        6 kB
        Aran Donohue

        Activity

        Aran Donohue made changes -
        Attachment arbitrary.patch [ 12448827 ]
        Aran Donohue made changes -
        Attachment arbitrary.patch [ 12438156 ]
        Aran Donohue made changes -
        Field Original Value New Value
        Attachment arbitrary.patch [ 12438156 ]
        Aran Donohue created issue -

          People

          • Assignee:
            Unassigned
            Reporter:
            Aran Donohue
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:

              Time Tracking

              Estimated:
              Original Estimate - 96h
              96h
              Remaining:
              Remaining Estimate - 96h
              96h
              Logged:
              Time Spent - Not Specified
              Not Specified

                Development