Generating Random Structurally Rich Algebraic Data Type Values

Generating Random Structurally Rich Algebraic Data Type Values

Generating Random Structurally Rich Algebraic Data Type Values Agust´ın Mista Alejandro Russo Chalmers University of Technology Chalmers University of Technology Gothenburg, Sweden Gothenburg, Sweden [email protected] [email protected] Abstract—Automatic generation of random values described by are well-typed, they might not be built with enough structure algebraic data types (ADTs) is often a hard task. State-of-the-art to penetrate into deep software layers. random testing tools can automatically synthesize random data In this work, we identify two different sources of structural generators based on ADTs definitions. In that manner, generated values comply with the structure described by ADTs, something information that can be statically exploited to improve the that proves useful when testing software which expects complex generation process of ADT values (Section III). Then, we inputs. However, it sometimes becomes necessary to generate show how to capture this information into our (automatically) structural richer ADTs values in order to test deeper software derived random generators. More specifically, we propose layers. In this work we propose to leverage static information a generation process that is capable of considering how found in the codebase as a manner to improve the generation process. Namely, our generators are capable of considering how programs branch on input ADTs values as well as how they get programs branch on input data as well as how ADTs values manipulated by abstract interfaces (Section IV). Furthermore, are built via interfaces. We implement a tool, responsible for we show how to predict the expected distribution of the ADT synthesizing generators for ADTs values while providing compile- constructors, values fitting certain branching patterns, and time guarantees about their distributions. Using compile-time calls to interfaces that our random generators produce. For predictions, we provide a heuristic that tries to adjust the distribution of generators to what developers might want. We that, we extend some recent results on applying branching report on preliminary experiments where our approach shows processes [14]—a simple stochastic model conceived to study encouraging results. population growth (Section V). We implement our ideas as an Index Terms—random testing, algebraic data types, Haskell extension of the already existing derivation tool called [9]. We call our extension as 1 to make it easy the I. INTRODUCTION distinction for the reader. is capable of automatically Random testing is a promising approach for finding bugs synthesizing QuickCheck generators which produce rich ADT [1]–[3]. QuickCheck [4] is the dominant tool of this sort used values, where the distributions of random values can be adjusted by the Haskell community. It requires developers to specify (i) at compile-time to what developers might want. Finally, we testing properties describing programs’ expected behavior and provide empirical evaluations showing that including static (ii) random data generators based on the types of the expected information from the user codebase improves the code coverage inputs (e.g., integers, strings, etc.). QuickCheck then generates of two external applications when tested using random values random test cases and reports violating testing properties. generated following our ideas (Section VI). QuickCheck comes equipped with random generators for We remark that, although this work focuses on Haskell built-in types, while it requires to manually write generators algebraic data types, this technique is general enough to be for user-defined ADTs. Recently, there has been a proliferation applied to most programming languages. of tools to automatically derive QuickCheck generators for ADTs [5]–[9]. The main difference about these tools lies on the II. BACKGROUND guarantees provided to ensure the termination of the generation In this section, we briefly introduce the common approach process and the distribution of random values. Despite their for automatically deriving random data generators for ADTs in differences, these tools guarantee that generated values are well- QuickCheck. To exemplify this, and for illustrative purposes, typed. In other words, generated values follow the structure let us consider the following ADT definition to encode simple described by ADT definitions. Html pages: Well-typed ADT values are specially useful when testing programs which expect highly structured inputs like compilers data Html= Text String [10]–[12]. Generating ADT values also proves fruitful when j Single String looking for vulnerabilities in combination with fuzzers [8], j Tag String Html [13]. Despite these success stories, ADT type-definitions do j Join Html Html not often capture all the invariants expected from the data that they are intended to model. As a result, even if random values 1 is available at http://github.com/OctopiChalmers/dragen2 The type Html allows to build pages via four possible Join constructor, it also generates two independent random constructions: Text—which represents plain text values—, sub-expressions recursively, decreasing the generation size by a Single and Tag—which represent singular and paired HTML unit on each recursive invocation (smaller genHtml). The case tags, respectively—, and Join—which concatenates two HTML of random generation of Tag constructors follows analogously. pages one after another. In Haskell, Text, Single, Tag, and This random process keeps calling itself recursively until the Join are known as data constructors (or constructors for short) generation size reaches zero, where the generator is constrained and are used to distinguish which variant of the ADT we are to pick among terminal data constructors, being Text and constructing. Each data constructor is defined as a product of Single the only possible choices in our particular case. zero or more types known as fields. For instance, Text has a The previous definition is rather mechanical, except per- field of type String, whereas Join has two recursive fields of haps for the chosen generation frequencies. [9] is type Html. In general, we will say that a data constructor with a tool conceived to mitigate the problem of finding the no recursive fields is terminal, and non-terminal or recursive if appropriated generation frequencies. It uses the theory of it has at least one field of such nature. With this representation, branching processes [14] to model and predict analytically the the example page <html>hello<hr>bye</html> can be expected number of generated data constructors. This prediction encoded as: mechanism is used to feedback a simulation-based optimization Tag "html" (Join(Join process that adjusts the generation frequency of each data (Text "hello")(Single "hr")) (Text "bye")) constructor in order to obtain a particular distribution of values that can be specified by the user—thus providing a flexible A. Type-driven generation of random values testing environment while still being mostly automated. In order to generate random ADTs values, most approaches As many other tools for automatic derivation of generators require users to provide a random data generator for each (e.g., [5]–[7], [13]), synthesizes random generators ADT definition. This is a cumbersome and error prone task similar to the one shown before, where the generation process that usually follows closely the structure of the ADTs. For is limited to pick a single data constructor at the time instance, consider the following definition of a QuickCheck and then recursively generate each required sub-expression random generator for the type Html: independently. In practice, this procedure is often too generic to generate random data with enough structural complexity genHtml = sized( λsize ! required for testing certain applications. if size ==0 then frequency III. SOURCES OF STRUCTURAL INFORMATION [(2; Text h$i genString) In this section, we describe the motivation for considering ; (1; Single h$i genString)] two additional sources of structural information which lead else frequency us to obtain better random data generators. We proceed to [(2; Text h$i genString) exemplify the need to consider such sources with examples. ; (1; Single h$i genString) ; (4; Tag h$i genString h∗i smaller genHtml) A. Branching on input data ; (3; Join h$i smaller genHtml h∗i smaller genHtml)]) To exemplify the first source of structural information, We use the Haskell syntax [] and (; ) for denoting lists consider that we want to use randomly generated Html values and pairs of elements, respectively (e.g., [(1; 2); (3; 4)] is a to test a function simplify:: Html ! Html. In Haskell, the notation f::T means that program f has type T. In our example, list of pairs of numbers.) The random generator genHtml is defined using QuickCheck’s function sized to parameterize the function simplify takes an Html as an input and produces generation process up to an external natural number known an Html value as an output—thus its type Html ! Html. as the generation size—captured in the code with variable Intuitively, the purpose of this function is to assemble sequences size. This parameter is chosen by the user, and it is used to of Text constructors into a single big one. More specifically, limit the maximum amount of recursive calls that this random the code of simplify is as follows: generator can perform and thus ensuring the termination of simplify:: Html ! Html the generation process. When called with a positive generation simplify(Join(Textt 1)(Textt 2)) size, this generator can pick to generate among any Html data = Text(concatt 1 t2) constructor with an explicitly generation frequency that can simplify(Join(Join(Textt 1)x)y) be chosen by the user—in this example, 2, 1, 4 and 3 for = simplify(Join(Textt 1)(simplify(Joinxy))) Text, Single, Tag, and Join, respectively. When it picks to simplify(Joinxy)= Join(simplifyx)(simplifyy) generate a Text or a Single data constructor, it also generates a simplify(Tagtx) = Tagt(simplifyx) random String value using the standard QuickCheck generator simplifyx=x 2 genString. On the other hand, when it picks to generate a Function concat just concatenates two strings.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    7 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us