Uploaded image for project: 'Thrift'
  1. Thrift
  2. THRIFT-728

Make generated Haskell code an instance of Arbitrary

    XMLWordPrintableJSON

Details

    • 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.

      Attachments

        1. arbitrary.patch
          6 kB
          Aran Donohue

        Issue Links

          Activity

            People

              roger Roger Meier
              aran_donohue Aran Donohue
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

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