Click here to monitor SSC
Andrew Clarke

The Waffle Generator

16 January 2008

Sometimes, silly programs have a less obvious useful purpose. Andrew Clarke takes his classic 'Waffle Generator', and provides it in various forms, including a CSS Stylesheet tester, and as a Generator for SQL Data Generator. The Waffle Generator puts text into your test database!

Waffle

This article provides the source of a utility, the Waffle Generator, which will fill your database or website with ridiculous and turgid prose. This is not, as you might initially suspect, designed as a crutch for desperate Bloggers, but to test out software. The perfect test data is as much like the real data as possible, but rather wilder, and more random.

In this article, I provide the source for both a PHP version and a C# version of the Waffle Generator. I also show you how to make it into a custom generator for the new SQL Data Generator.

A Brief History of the Waffle Generator

I originally wrote the Waffle Generator way back in the mid 1980s, long before the Web. I started work on it when I first met the redoubtable 'Phil Factor'. Even then, he had a strong anarchic streak to his nature. We were working in a large Multinational together, and both driven to screaming pitch by the poor use of English in company documents, marketing information, and in IT discussions and meetings. We developed our collection of words and phrases by noting down the ridiculous examples used in meetings during our work there as IT consultants, and incorporating them into the collection.

Based on this word bank, The Waffle Generator produces reams and reams of text which, on first glance, looks like real, ponderous, prose; replete with clichés. The following paragraph typifies its output (try it for yourself here: Press F5 occasionally!).

'Regarding the nature of any three-tier subjective classification, the total delivery presents extremely interesting challenges to the sanctioned Philosophical theme. The interface is of a interactive nature. To reiterate, the classic definition of the consolidation of the interpolation of antithesis underlines the essential paradigm of the negative aspects of any marginalised interface. It might seem reasonable to think of a proven solution to the performance objectives as involving the legitimate principal milieu. Nevertheless, a concept of what we have come to call the strategic goals provides a heterogeneous environment to the evidence of feeling. On the other hand, a realization the importance of the core business is reciprocated by the negative aspects of any proactive auxiliary teleology. There is probably no causal link between the three-phase empirical transformation and the principle of the diverse hardware environment. However the target population for the consolidation of the compatible central expression necessitates that urgent consideration should be applied to what is beginning to be termed the "ad-hoc inductive projection". Based on integral subsystems, examination of inclusive instances provides a harmonic integration with the social dichotomy. This should be considered in the light of the functional baseline.'

We chose this as a programming example because it is so simple, and because it demonstrates that the best way to produce language automata is to mimic the way we construct language. It displays a simple and valid use of recursion. Above all, it is fun to use. Obviously, the serious user will bring his own word and phrase-banks to bear on it.

I put the Generator in the Public Domain and it was certainly the first of such programs to be so placed. Originally, it was written for a primitive C compiler to run on CP/M. From these humble beginnings, the program has taken on a life of its own, and is irrepressibly popular, unlike the vast majority of the code we write.

It has been used, developed and exploited by two generations of IT people and has been translated into a variety of other languages. Phil, who has since been a great fan of this type of programming, has published a variant in SQL on Simple-Talk, called 'The Excuse Generator'. There is also a PHP version that I wrote to test out CSS Stylesheets. The output is in strict 'core' HTML, and it is handy for checking that Stylesheets work with unpredictable sizes of text. You can get it here and I explain how to use it here.

The Generator has been used in numerous, serious development projects. For a long time, BT at Martlesham Heath, UK, used the Waffle Generator to test comms lines. However, we've also had 'thank you' letters from desperate PhD students who bulked up their Thesis with this handy tool.

The singular peak of achievement was when the output of the Waffle Generator was submitted by a prankster to the Journal of Theoretical Psycholinguistics, was praised by two independent referees and published. I still have the article. As a tribute, some phrases from this exercise are enshrined in the Generator's word-bank.

The Waffle Generator Source

The program itself is very simple. Following is the basic C# code, which could slot straight into any C# application. Here, we sticking to the simplest approach of using static wordbanks But I once did a VB version, with a built-in Text editor with word-banks that could be read in and customized for writing school reports, academic essays, and thank-you letters.

Unfortunately the source of the C# version is a bit too long for the body of the article but there is an HTML version here and a text version here.  The latest version is now on Codeplex with the other custom generators for SQL Data Generator  on Red Gate SQL Data Generator Community Generators

Using the Waffle Generator with SQL Data Generator

There was a time that one would need to hack together a user-interface. No longer, as we can now make it into a Generator for SQL Data Generator. As this is in Beta form, you will have to roll up your sleeves and build the DLL from the source code. (the DLL is version-specific)

Firstly, we'll need the  SQL Data Generator. Don't worry, you can download it for fifteen days free.

To do this generator we create a Class Library .NET Project. (Visual C# 2005 Express edition will work fine and is free) We must add references to RedGate­.SQLDataGenerator­.Engine and RedGate­.SQLCompare.­Engine.

Firstly, we create the basic functionality. (see the C# code above) Then we create a public class that inherits the GeneratorBase, add the class attributes and Implement the constructor.

We create a file called WaffleGenerator.CS (we also provide the source to this as an attachment to the article). You'll see that you provide, as attributes to the generator class, a category, a name and a description for the generator. You can then provide clues for the search of a data type. Here we say that the string 'HTML' or 'Text' in a column name gives the Waffle generator a score of 10. This means that the Waffle generator would be likely to be selected automatically for a column like 'ArticleHTML'. You can change this to your own taste. We then provide the parameters with their defaults, to be included in the SQL Data Generator form.

using System;

using System.Collections;

using System.Text;

using RedGate.SQLDataGenerator.Engine.Generators;

using RedGate.SQLDataGenerator.Engine.Generators.Static;

using RedGate.SQLDataGenerator.Engine.Generators.Support;

 

/* We implement a special constructor that takes a single parameter of type GeneratorParameters. This parameter describes the SQL field in the Table that is being assigned. We can throw exceptions etc within the constructor if we wish
In order for the generator to appear within the UI, we add a simple Generator attribute to the class.
*/

namespace SimpleTalk.WaffleGenerator

{

    [Generator(typeof(string), "Generic", "Waffle Generator", "Creates quantities of Waffle")]

    [Matches(".*Html.*", 10)]

    [Matches(".*Text.*", 10)]

/*The Generator attribute should only be defined once per class and defines the the type of the .NET result, the Category that the generator is placed in, the name and the description of the generator in the UI.*/

    public class WaffleGenerator : GeneratorBase

    {

        private int m_Paragraphs = 10;

        private Boolean m_HTML = true;

        private Boolean m_Headings = true;

 

        public int Paragraphs

        {

            get { return m_Paragraphs; }

            set

            {

                if(m_Paragraphs < 0)

                {

                    throw new ArgumentException("You must specify a positive number of Paragraphs");

                }

                m_Paragraphs = value;

            }

        }

        public Boolean HTML

        {

            get { return m_HTML; }

            set

             {

            m_HTML=value;

        }

        }

        public Boolean Headings

        {

            get { return m_Headings; }

            set

            {

                m_Headings = value;

            }

 

        }

      

        public WaffleGenerator(GeneratorParameters parameters) : base(parameters)

        {

        }

 

        public override IEnumerator GetNonNullEnumerator()

        {

            Random r = new Random(m_Seed);

            StringBuilder sb = new StringBuilder();

            WaffleEngine we = new WaffleEngine(r);

 

            if (m_HTML)

            {

                while (true)

                {

                    we.HtmlWaffle(m_Paragraphs, m_Headings, sb);

                    yield return sb.ToString();

                    sb.Length = 0;

                }

            }

            else

            {

                while (true)

                {

                    we.TextWaffle(m_Paragraphs, m_Headings, sb);

                    yield return sb.ToString();

                    sb.Length = 0;

                }

            }

        }

    }

}

When the SQL Data Generator starts-up, it scans a directory (normally the 'generators' subdirectory, for DLLs. Each of these DLLs in turn is loaded up and reflection is used to see if any public classes implement these interfaces. If this is the case then they are accessible to the application as 'custom generators'.

This means that you can, if you are brave, you can configure the project so that the output DLL is written to (normally) %Program Files%­\Red Gate­\SQL Data Generator 1­\Generators­\ . If cautious, you can wait until a DLL is built, and then you can merely 'release it' by copying it directly into the SQL Data Generator's Generator subdirectory, as follows:

When you subsequently start up the SQL Data Generator,  you will find that the custom generator is now listed alongside the others. If you use Beta 2, then you will have to rename the Waffle Generator to something else. All other Beta versions should work fine.

You'll see that it has picked up the name and description. This all comes from our "IGenerator" Interface

Then, you just enable data generation for a text column in a suitable table and out comes plausible text by the yard. Just to test it out, create a table as follows:

CREATE TABLE [dbo].[waffle](
  
[Waffle_ID] [int] IDENTITY(1,1) NOT NULL,
  
[Waffle] [varchar](MAX) NOT NULL
)
ON [PRIMARY]

You will find that suddenly you have as much text as you can cope with, ready for you to try out that wonderful RegEx or indexing algorithm.

So, based on this example, why not write an excuse generator for an IT operational failure, based on Simon Travaglia's excellent word-bank

…or more to the point, when you're testing your database-driven application, you can refine the plausibility of your spoof data to the point where you never have to look longingly at your live system, replete with all its confidential, financial and commercial information. Demos and presentations will never be the same again.

Links and Trivia

 

Andrew Clarke

Author profile:

Andrew Clarke has been developing software applications for over 35 years. He is a database expert, but also has had many years of experience in designing and programming applications and software tools. He has a particular interest in website-publishing and ECommerce. Before joining Redgate, he worked with the first two winners of the 'Apprentice' program at Amstrad, creating various business applications, He is the editor of Simple-Talk.

Search for other articles by Andrew Clarke

Rate this article:   Avg rating: from a total of 18 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Excellent
Posted by: David Connell (view profile)
Posted on: Thursday, January 17, 2008 at 8:43 AM
Message: Really cool,
The only change I would do is make the constructor auto-assign your HTML member variable depending if the Field Name contains HTML. (ie like your matches.)
Really cool.
David

Subject: Brilliant
Posted by: John Bower (not signed in)
Posted on: Friday, January 18, 2008 at 5:27 AM
Message: The Waffle Generator has always been one of my favourite apps. I wonder if it's the reason Phil's book is as long as it is...

Subject: Code for this article
Posted by: Andrew Clarke (view profile)
Posted on: Thursday, February 14, 2008 at 4:31 AM
Message: In case anyone else gets stuck, the code is in the speech-bubble at the top of the article. You may need to delete the AssemblyInfo reference...

Subject: The Waffle Generator lives on
Posted by: Phil Factor (view profile)
Posted on: Monday, April 07, 2008 at 12:57 PM
Message: The waffle generator now lives at:

http://www.codeplex.com/SDGGenerators




 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.