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

Make generated Haskell code an instance of Arbitrary

VotersWatch issueWatchersLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

    Details

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

        Attachments

        Issue Links

          Activity

            People

            • Assignee:
              roger Roger Meier
              Reporter:
              aran_donohue Aran Donohue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

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

                  Issue deployment