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

 



This article has been viewed 5582 times.
Andrew Clarke

Author profile: Andrew Clarke

Andrew Clarke has been developing software applications for over 25 years. He is a database expert, but has a particular interest in website-publishing and ECommerce. He recently worked with the first two winners of the 'Apprentice' program at Amstrad, creating various business applications, and since worked with Tim Campbell setting up the 'Bright Ideas Trust'. He also subedits and reviews articles for Simple-Talk.

Search for other articles by Andrew Clarke

Rate this article:   Avg rating: from a total of 15 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




 






recommended site pinvoke

PInvoke.net is a user-driven wiki which provides .NET developers with native method signatures, so they don't have to spend time writing them from scratch.





Damon Armstrong
Customizing the Login Page in SharePoint 2007
 Damon shows how a few simple steps lead you to being able to include the login form in a consistent look and feel to...  Read more...


ANTS Profiler and the Un-Rest Cure
 After a while, successful applications can get set in their ways. Bart Read and Andrew Hunter decided... Read more...

Silverlight-Speed Loop
 John Bower steps up a gear, produces a Lamborghini, and examines the process of using a high-speed... Read more...

Sid: Vicious
 Dan Archer documents his epic struggle with an apparently simple task of authenticating user... Read more...

Embedding Help so it will be used
 It is not good enough to make assumptions about the way that users go about getting help when they use... Read more...

Optimising a High-Performance Computing Tool
 Many computer systems nowadays have their ‘correctness’ checked using sample testing, but this isn't... Read more...

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

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. 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...

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

Beginning ASP.NET 2.0
 It seems that there is both excitement and confusion surrounding Master Pages and Themes. A big part of... Read more...

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

Join Simple Talk