Two Case Studies: QuickCheck and Wash/CGI Lecture 4, Designing and Using Combinators John Hughes.

Slides:



Advertisements
Similar presentations
Cookies, Sessions. Server Side Includes You can insert the content of one file into another file before the server executes it, with the require() function.
Advertisements

Java Script Session1 INTRODUCTION.
Domain Specific Embedded Languages Lecture 2, Designing and Using Combinators John Hughes.
Copyright 2004 Monash University IMS5401 Web-based Systems Development Topic 2: Elements of the Web (g) Interactivity.
1 Frameworks. 2 Framework Set of cooperating classes/interfaces –Structure essential mechanisms of a problem domain –Programmer can extend framework classes,
CS 290C: Formal Models for Web Software Lecture 10: Language Based Modeling and Analysis of Navigation Errors Instructor: Tevfik Bultan.
Test Data Generators Lecture 5. Why Distinguish Instructions? Functions always give the same result for the same arguments Instructions can behave differently.
Introducing Monads Lecture 3, Designing and Using Combinators John Hughes.
Chapter 11 ASP.NET JavaScript, Third Edition. 2 Objectives Learn about client/server architecture Study server-side scripting Create ASP.NET applications.
CS510AP Quick Check Monads. QuickCheck Quick check is a Haskell library for doing random testing. You can read more about quickcheck at –
Computer Science 101 Web Access to Databases Overview of Web Access to Databases.
Mgt 240 Lecture Website Construction: Software and Language Alternatives March 29, 2005.
C++ fundamentals.
CGI Programming: Part 1. What is CGI? CGI = Common Gateway Interface Provides a standardized way for web browsers to: –Call programs on a server. –Pass.
Creating Web Page Forms
Christopher M. Pascucci Basic Structural Concepts of.NET Browser – Server Interaction.
Form Handling, Validation and Functions. Form Handling Forms are a graphical user interfaces (GUIs) that enables the interaction between users and servers.
©Ian Sommerville 2004Software Engineering, 7th edition. Chapter 13 Slide 1 Application architectures.
1 Web Developer & Design Foundations with XHTML Chapter 6 Key Concepts.
INTRODUCTION TO WEB DATABASE PROGRAMMING
Lecture 3 – Data Storage with XML+AJAX and MySQL+socket.io
4-Sep-15 HTML Forms Mrs. Goins Web Design Class. Parts of a Web Form A Form is an area that can contain Form Control/Elements. Each piece of information.
FALL 2005CSI 4118 – UNIVERSITY OF OTTAWA1 Part 4 Web technologies: HTTP, CGI, PHP,Java applets)
CSCI 6962: Server-side Design and Programming Course Introduction and Overview.
JavaScript & jQuery the missing manual Chapter 11
Chapter 33 CGI Technology for Dynamic Web Documents There are two alternative forms of retrieving web documents. Instead of retrieving static HTML documents,
Chapter 16 The World Wide Web Chapter Goals Compare and contrast the Internet and the World Wide Web Describe general Web processing Describe several.
XHTML Introductory1 Forms Chapter 7. XHTML Introductory2 Objectives In this chapter, you will: Study elements Learn about input fields Use the element.
Erlang/QuickCheck Thomas Arts, IT University John Hughes, Chalmers University Gothenburg.
1 VU. 2 CS101 Introduction to Computing Lecture 15 More on Interactive Forms (Web Development Lecture 5)
Introduction to JavaScript + More on Interactive Forms.
IST 210: PHP BASICS IST 210: Organization of Data IST210 1.
9 Chapter Nine Compiled Web Server Programs. 9 Chapter Objectives Learn about Common Gateway Interface (CGI) Create CGI programs that generate dynamic.
Lecture Set 14 B new Introduction to Databases - Database Processing: The Connected Model (Using DataReaders)
11 Web Services. 22 Objectives You will be able to Say what a web service is. Write and deploy a simple web service. Test a simple web service. Write.
Tutorial 7 Creating Forms. Objectives Session 7.1 – Create an HTML form – Insert fields for text – Add labels for form elements – Create radio buttons.
Chapter 34 Java Technology for Active Web Documents methods used to provide continuous Web updates to browser – Server push – Active documents.
Lecturer: Prof. Piero Fraternali, Teaching Assistant: Alessandro Bozzon, Advanced Web Technologies: Struts–
INTRODUCTION TO JAVASCRIPT AND DOM Internet Engineering Spring 2012.
Active Server Pages  In this chapter, you will learn:  How browsers and servers interacted on the Internet when the Internet first became popular 
Chapter 8 Collecting Data with Forms. Chapter 8 Lessons Introduction 1.Plan and create a form 2.Edit and format a form 3.Work with form objects 4.Test.
Website Development with PHP and MySQL Saving Data.
 Whether using paper forms or forms on the web, forms are used for gathering information. User enter information into designated areas, or fields. Forms.
Chapter 6 Server-side Programming: Java Servlets
1 Welcome to CSC 301 Web Programming Charles Frank.
Forms and Server Side Includes. What are Forms? Forms are used to get user input We’ve all used them before. For example, ever had to sign up for courses.
1 © Netskills Quality Internet Training, University of Newcastle HTML Forms © Netskills, Quality Internet Training, University of Newcastle Netskills is.
1 MSCS 237 Overview of web technologies (A specific type of distributed systems)
Java server pages. A JSP file basically contains HTML, but with embedded JSP tags with snippets of Java code inside them. A JSP file basically contains.
© M. Winter COSC 4P41 – Functional Programming Programming with actions Why is I/O an issue? I/O is a kind of side-effect. Example: Suppose there.
Introduction to JavaScript CS101 Introduction to Computing.
Server-side Programming The combination of –HTML –JavaScript –DOM is sometimes referred to as Dynamic HTML (DHTML) Web pages that include scripting are.
Producing a high-impact web experience by integrate Macromedia Flash and ASP By Katie Tuttle CS 330: Internet Architecture and Programming Project.
1 WWW. 2 World Wide Web Major application protocol used on the Internet Simple interface Two concepts –Point –Click.
David Lawrence 7/8/091Intro. to PHP -- David Lawrence.
Implementing and Using the SIRWEB Interface Setup of the CGI script and web procfile Connecting to your database using HTML Retrieving data using the CGI.
JS (Java Servlets). Internet evolution [1] The internet Internet started of as a static content dispersal and delivery mechanism, where files residing.
Web Design and Development. World Wide Web  World Wide Web (WWW or W3), collection of globally distributed text and multimedia documents and files 
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Interactive Programs: I/O and Monads Dr. Hyunyoung Lee.
Module: Software Engineering of Web Applications Chapter 2: Technologies 1.
©SoftMooreSlide 1 Introduction to HTML: Forms ©SoftMooreSlide 2 Forms Forms provide a simple mechanism for collecting user data and submitting it to.
8 Chapter Eight Server-side Scripts. 8 Chapter Objectives Create dynamic Web pages that retrieve and display database data using Active Server Pages Process.
1 CSC160 Chapter 1: Introduction to JavaScript Chapter 2: Placing JavaScript in an HTML File.
IST 210: PHP Basics IST 210: Organization of Data IST2101.
111 State Management Beginning ASP.NET in C# and VB Chapter 4 Pages
Test Data Generators. Why Distinguish Instructions? Functions always give the same result for the same arguments Instructions can behave differently on.
1 Chapter 1 INTRODUCTION TO WEB. 2 Objectives In this chapter, you will: Become familiar with the architecture of the World Wide Web Learn about communication.
Section 10.1 Define scripting
Test Data Generators.
PHP / MySQL Introduction
Presentation transcript:

Two Case Studies: QuickCheck and Wash/CGI Lecture 4, Designing and Using Combinators John Hughes

Motivations Two case studies (software testing, server-side web scripting) in which a DSEL played an essential rôle. Two DSELs with a monadic design. Three interesting monads!

QuickCheck: The Research Hypothesis Formal specifications can be used directly for software testing in combination with random test case generation. Needed: a language to express formal specifications. a way to specify test case generation. a tool to carry out tests.

QuickCheck: The Research Hypothesis Formal specifications can be used directly for software testing in combination with random test case generation. Needed: a language to express formal specifications. a way to specify test case generation. a tool to carry out tests. Solution: a DSEL! Implemented in 350 lines of code.

A “Demo” prop_PlusAssoc x y z = (x + y) + z == x + (y + z) Property encoded as a Haskell function Main> quickCheck prop_PlusAssoc Invoke quickCheck to test it

A “Demo” prop_PlusAssoc x y z = (x + y) + z == x + (y + z) Main> quickCheck prop_PlusAssoc ERROR - Unresolved overloading *** Type : (Num a, Arbitrary a) => IO () *** Expression : quickCheck prop_PlusAssoc

A “Demo” prop_PlusAssoc :: Integer -> Integer -> Integer -> Bool prop_PlusAssoc x y z = (x + y) + z == x + (y + z) Main> quickCheck prop_PlusAssoc OK, passed 100 tests.

A “Demo” prop_PlusAssoc :: Float -> Float -> Float -> Bool prop_PlusAssoc x y z = (x + y) + z == x + (y + z) Main> quickCheck prop_PlusAssoc Falsifiable, after 0 tests: Values for x, y, and z

A “Demo” prop_Insert :: Integer -> [Integer] -> Bool prop_Insert x xs = ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs))

A “Demo” prop_Insert :: Integer -> [Integer] -> Bool prop_Insert x xs = ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs)) QuickCheck> quickCheck prop_Insert Falsifiable, after 2 tests: -3 [3,-4,3]

A “Demo” prop_Insert :: Integer -> [Integer] -> Property prop_Insert x xs = ordered xs ==> ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs)) Main> quickCheck prop_Insert OK, passed 100 tests.

A “Demo” prop_Insert :: Integer -> [Integer] -> Property prop_Insert x xs = ordered xs ==> collect (length xs) $ ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs)) Investigate test coverage

A “Demo” prop_Insert :: Integer -> [Integer] -> Property prop_Insert x xs = ordered xs ==> collect (length xs) $ ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs)) Main> quickCheck prop_Insert OK, passed 100 tests. 46% 0. 26% 1. 19% 2. 8% 3. 1% 4.

A “Demo” prop_Insert :: Integer -> [Integer] -> Property prop_Insert x xs = ordered xs ==> collect (length xs) $ ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs)) Main> quickCheck prop_Insert OK, passed 100 tests. 46% 0. 26% 1. 19% 2. 8% 3. 1% 4. A random list is unlikely to be ordered unless it is very short!

A “Demo” prop_Insert :: Integer -> Property prop_Insert x = forAll orderedList $ \xs -> collect (length xs) $ ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs))

A “Demo” prop_Insert :: Integer -> Property prop_Insert x = forAll orderedList $ \xs -> collect (length xs) $ ordered (insert x xs) ordered xs = and (zipWith (<=) xs (drop 1 xs)) Main> quickCheck prop_Insert OK, passed 100 tests. 20% 2. 17% 0. 15% 1. 11% 3. 9% 5. 7% 4. 5% 8. 3% 9. 3% 7. 3% 11. 2% 14. 1% 6. 1% 19. 1% 15. 1% 13. 1% 10.

Property Language property ::= boolExp | \x -> property | boolExp ==> property | forAll set $ \x -> property | collect expr property test ::= quickCheck property

Set = Test Data Generator orderedList :: (Ord a, Arbitrary a) => Gen [a] orderedList = oneof [return [], do xs <- orderedList n <- arbitrary return ((case xs of [] -> n x:_ -> n `min` x) :xs)] Random choice Generator: a monad! Type based generation

Set = Test Data Generator orderedList :: (Ord a, Arbitrary a) => Gen [a] orderedList = frequency [(1,return []), (4,do xs <- orderedList n <- arbitrary return ((case xs of [] -> n x:_ -> n `min` x) :xs))] Specified distribution

Type Based Generation class Arbitrary a where arbitrary :: Gen a instance Arbitrary Integer where … instance (Arbitrary a, Arbitrary b) => Arbitrary (a,b) where … instance Arbitrary a => Arbitrary [a] where … Defines default generation method by recursion over the type!

Type Based Testing class Testable a where property :: a -> Property instance Testable Bool where … instance (Arbitrary a, Show a, Testable b) => Testable (a->b) where property f = forAll arbitrary f quickCheck :: Testable a => a -> IO () Testing by recursion on types.

Generation Language gen ::=return expr |do {x <- gen}* gen |arbitrary | oneof [gen*] | frequency [(int,gen)*] How does the Gen monad work?

Random Numbers in Haskell class RandomGen g where next :: g -> (Int, g) split :: g -> (g, g) A random number seed can be split into two independent seeds. Idea Parameterise actions on a random number seed. >>= supplies independent seeds to its operands.

A Generator Monad Transformer newtype Generator g m a = Generator (g -> m a) instance (RandomGen g, Monad m) => Monad (Generator g m) where return x = Generator $ \g -> return x Generator f >>= h = Generator $ \g -> let (g1,g2) = split g in do a <- f g1 let Generator f' = h a f' g2

Representation of Properties newtype Property = Prop (Gen Result) Generates a test result! data Result = Result { ok :: Maybe Bool, arguments :: [String], stamp :: [String]} forAll collect

Did it Work? Only 350 lines, but the combination of specifications and random testing proved very effective. Used by Okasaki (Columbia State) to develop data structure library Andy Gill to develop a Java (!) pretty-printing library Team Functional Beer in the ICFP Programming Contest Galois Connections, likewise Safelogic, to develop transformer for first order logic Ported to Mercury i.e. used in Swedish and US industry

Current Work: Testing Imperative ADTs Specify ADT operations by a simple Haskell implementation. type Queue a = [a] empty = [] add x q = x:q front (x:q) = x remove (x:q) = q

Current Work: Testing Imperative ADTs Specify ADT operations by a simple Haskell implementation. Construct imperative implementation. data QueueI r a = Queue (r (QCell r a)) (r (QCell r a)) addI :: RefMonad m r => a -> Queue r a -> m ()

Current Work: Testing Imperative ADTs Specify ADT operations by a simple Haskell implementation. Construct imperative implementation. Model a language of operations as a datatype, with interpretations on specification and implementation. data Action a = Add a | Front | Remove spec :: [Action a] -> Queue a -> Queue a impl :: RefMonad m r => [Action a] -> QueueI r a -> m ()

Current Work: Testing Imperative ADTs Specify ADT operations by a simple Haskell implementation. Construct imperative implementation. Model a language of operations as a datatype, with interpretations on specification and implementation. retrieve :: RefMonad m r => QueueI r a -> m (Queue a) Define retrieval of the implementation state.

Current Work: Testing Imperative ADTs Specify ADT operations by a simple Haskell implementation. Construct imperative implementation. Model a language of operations as a datatype, with interpretations on specification and implementation. prop_Queue = forAll actions $ \as -> runST (do q <- emptyI impl as q abs <- retrieve q return (abs==spec as empty)) Define retrieval of the implementation state. Compare results after random sequences of actions.

Future Work Use Haskell’s foreign function interface to test software in other languages. Haskell ==> executable specification language QuickCheck ==> specification based testing system

QuickCheck Summary QuickCheck is a state-of-the-art testing tool. DSEL approach made the tool extremely easy to construct and modify, let us experiment, identify and solve problems not previously addressed. Could not have carried out the same research without it!

QuickCheck Summary QuickCheck is a state-of-the-art testing tool. DSEL approach made the tool extremely easy to construct and modify, let us experiment, identify and solve problems not previously addressed. Could not have carried out the same research without it! A recent paper on a similar idea for C used the string copy function as the case study! ?

Wash/CGI: The Goal Ease the programming of active web pages, implemented using the CGI interface. The CGI interface provides server side scripting, via programs which generate HTML running on the server -- in contrast to e.g. Javascript or applets, which run in the browser. Most suitable for e.g. querying/updating databases on the server, where instant response is not important. An “old” standard, therefore portable: supported by all servers.

Counter Example main = run $ counter 0 counter n = ask $ standardPage "Counter" $ makeForm $ do text "Current counter value " text (show n) br empty submitField (counter (n+1)) (fieldVALUE "Increment")

Counter Example main = run $ counter 0 counter n = ask $ standardPage "Counter" $ makeForm $ do text "Current counter value " text (show n) br empty submitField (counter (n+1)) (fieldVALUE "Increment") Run function

Counter Example main = run $ counter 0 counter n = ask $ standardPage "Counter" $ makeForm $ do text "Current counter value " text (show n) br empty submitField (counter (n+1)) (fieldVALUE "Increment") Run function Create an active page

Counter Example main = run $ counter 0 counter n = ask $ standardPage "Counter" $ makeForm $ do text "Current counter value " text (show n) br empty submitField (counter (n+1)) (fieldVALUE "Increment") Run function Create an active page Monad for HTML generation

Counter Example main = run $ counter 0 counter n = ask $ standardPage "Counter" $ makeForm $ do text "Current counter value " text (show n) br empty submitField (counter (n+1)) (fieldVALUE "Increment") Run function Create an active page Monad for HTML generation Callback function

counter n = ask $ standardPage "Counter" $ makeForm $ do text "Current counter value " activeInputField counter (fieldVALUE (show n)) submitField (counter (n+1)) (fieldVALUE "++") submitField (counter (n-1)) (fieldVALUE "--") Extended Counter

main = run$ ask$ page$ makeForm$ do text "File to upload: " file <- fileInputField empty submitField (receive (raw file)) (fieldVALUE "Send file") receive [f] = if take 2 (fileName f) == ".." then htell $ page $ text "Naughty!" else do io (writeFile ("uploaded.files/"++fileName f) (fieldContents f)) htell $ page $ text "File uploaded" File Uploader

main = run$ ask$ page$ makeForm$ do text "File to upload: " file <- fileInputField empty submitField (receive (raw file)) (fieldVALUE "Send file") receive [f] = if take 2 (fileName f) == ".." then htell $ page $ text "Naughty!" else do io (writeFile ("uploaded.files/"++fileName f) (fieldContents f)) htell $ page $ text "File uploaded" File Uploader Creates an input field and delivers the value input.

main = run$ ask$ page$ makeForm$ do text "File to upload: " file <- fileInputField empty submitField (receive (raw file)) (fieldVALUE "Send file") receive [f] = if take 2 (fileName f) == ".." then htell $ page $ text "Naughty!" else do io (writeFile ("uploaded.files/"++fileName f) (fieldContents f)) htell $ page $ text "File uploaded" File Uploader Creates an input field and delivers the value input. Can do I/O on the server

Lab Result Entry System

editPerson pn pr = ask $ page $ makeForm $ do text (forename pr++" "++aftername pr++", "++ pn++" ("++ pr++")") p empty text "Lab Results:" br empty gs <- sequence (map (editLab (labs pr)) labNames) br empty submitField (commit pn pr gs) (fieldVALUE "Submit changes") Pass name, personal number, and grades to callback

Lab Result Entry System commit pn pr gs = do io (do d <- getDate putRecord (PN pn) (pr{labs=updateLabs (labs pr) gs d})) mainPage "Database updated"

Wash/CGI Paradigm HTML is generated just by calling a function for each element. Input fields just return (a structure containing) the value input. Active elements (e.g. submit buttons) just invoke a “callback function”. State is recorded by parameter passing, in the usual way. A very simple and natural paradigm!

How CGI Works ClientServer CGI script

How CGI Works ClientServer CGI script User clicks on CGI script’s URL Request sent to server

How CGI Works ClientServer CGI script CGI script runs and outputs HTML

How CGI Works ClientServer CGI script HTML sent to browser Script is no longer running

How CGI Works ClientServer CGI script User fills in form and clicks submit button CGI script Form contents returned to server Often to be processed by a different CGI script

How CGI Works ClientServer CGI script CGI script Problems How do we save the state of the session between invocations? How do we ensure the second CGI script correctly interprets the form generated by the first?

Saving the State Where should the state be saved? On the server? On the client? What if the client just closes the window? -- How long should the state be saved? What if the client presses Back, and continues from a previous state? Each window saves the state of its session. Back is easy to handle. Implement using “hidden fields” in HTML forms.

How Can We Save the State? Wash/CGI implements an entire session by one CGI script. When the script is resumed, it is (of course) reinvoked at the beginning. The script decodes state stored in the browser input, and reruns the computation up to the point of last suspension. Rerunning purely functional code produces the same results -- but input/output might not! How can we rerun the script, without repeating any input/output it performed?

A Monad Transformer for Resumable Actions suspend :: Monad m => Resume m () resume :: Monad m => [String] -> Resume m a -> m (Either [String] a) once :: (Monad m, Show a, Read a) => Resume m a -> Resume m a Suspend and save state, in a restartable form The “run function”: start in a given state, either suspend or terminate State is a list of strings Do this once only: save result in the state

Example of Resuming liftR m = once (lift (lift m)) example = do liftR (putStr "Input? ") x <- liftR getLine suspend liftR (putStr (x++"\n")) Main> resume [] example Input? 23 Left ["()","\"23\"",""] Main> resume ["()","\"23\"",""] example 23 Right ()

Defining Resume The Resume monad needs two features: A state, containing (i)Saved results from previous runs (ii)Collected results for the next run An exception mechanism to enable an abrupt stop, delivering the current state.

Defining Resume type Resume m a = State ([String],[String]) (Exception [String] m) a Saved results Generated results State on suspension

Defining Resume type Resume m a = State ([String],[String]) (Exception [String] m) a resume :: Monad m => [String] -> Resume m a -> m (Either [String] a) resume old m = runException $ runState (old,[]) $ do a <- m return (Right a) `handleWith` \new -> return (Left new)

Defining Resume type Resume m a = State ([String],[String]) (Exception [String] m) a suspend :: Monad m => Resume m () suspend = do (old,new) <- readState case old of [] -> exception (reverse ("":new)) x:old' -> writeState (old',x:new)

Defining Resume type Resume m a = State ([String],[String]) (Exception [String] m) a once :: (Monad m, Show a, Read a) => Resume m a -> Resume m a once m = do (old,new) <- readState case old of [] -> do a <- m writeState (old,show a:new) return a a:old' -> do writeState (old',a:new) return (read a)

The CGI Monad Wash/CGI defines a monad CGI: Provides resumption as described here (but without explicitly using monad transformers) Maintains a state to generate unique field names in HTML forms Handles input fields in forms

How Input Fields Work a <- textInputField empty … … value a … Generate HTML for an input field Bound to the value input? ? How can we have the input value already?

How Input Fields Work a <- textInputField empty … … value a … Just a, or Nothing Generates HTML and returns Nothing on the first run. Decodes the value and returns Just a on subsequent runs. Better not try to use the value until after a suspension!

HTML Generation HTML is represented as a tree structure: table tr td

HTML Generation data ELEMENT_ = ELEMENT_ { tag :: String, attrs :: [ATTR_], elems :: [ELEMENT_] } | … HTML is represented as a tree structure:

HTML Monad Transformer type WithHTML m a = State ELEMENT_ m a HTML constructors add a new sub-ELEMENT_ to the current ELEMENT_ take as argument a WithHTML action, which adds their own sub-ELEMENT_s Typical type:WithHTML m a -> WithHTML m a

HTML Example table (sequence [tr (sequence [td (text (show (x*y))) | x <- [1..8]] | y <- [1..8]])

Wash/CGI Summary Wash/CGI brings new power to CGI programmers Solves two awkward problems: saving and restoring state across client interactions consistent generation and interpretation of forms The DSEL went through many versions: flexibility led to a very clean design in the end Exploits integration with Haskell through e.g. callback functions