wiki:mutations

Mutation Engine

This library allows to inject random modifications (mutations) into arbitrary programs. The mutations, their parameters and the code to be modified can be controlled or selected randomly by the library. Different mechanisms can be used to inject the mutations. The library is designed to allow to easily add new mutations via subclassing. The mutations can be used to evaluate test suites or programming tools.

How to Install

Add the following Monticello Repository in your Monticello browser. Open it, and load the package ConfigurationOfMutationEngine.

MCHttpRepository
	location: 'http://www.hpi.uni-potsdam.de/hirschfeld/squeaksource/MetacelloRepository'
	user: ''
	password: ''

After that, execute the following line in your workspace:

(ConfigurationOfMutationEngine project version: '1.0') load.

Wait, until all dependencies have been loaded into your image.

How to Use

1. Create instance of MutationFactory

The main aspect when creating a MutationFactory is to choose the mechanism, that will be used to inject mutations into the system. Choose one of the following:

MutationFactory onSourceCode

-> Mutations will be compiled directly into the system, using the same method used by browsers. Might be somewhat dangerous (if the image is saved while the mutation is applied, and the image crashes, the old state of the method cannot be restored automatically)

MutationFactory onMethodWrappers

-> Mutations will be applied wrapping the mutated methods by MethodWrappers. After a crash, the original state of the image can always be restored using MethodFactory cleanupMethodWrappers

2. Optional: Configure the MutationScope

The MutationFactory has an instance of type MutationScope called scope. It is required, when the method to be mutated should be selected randomly.

It is not set by default. Create an instance using MutationScope new and use the methods in the protocol 'scope manipulation' to populate the scope with methods, classes or packages.

3. Create a Mutation object

The methods of MutationFactory in the protocol 'mutation creation' create Mutation objects.

#createMutation:withParameters:forMethod: is the most general one, allowing to specify all parameters of Mutation creation explicitely.

#randomMutation chooses ALL parameters randomly.

All other methods allow to specify parts of the parameters explicitely, and choose the rest of the parameters randomly. Following aspects are relevant:

  • The Mutation class - specifies, which mutation will be created. Will be picked from all non-abstract subclasses of Mutation (assembled in MutationFactory class >> #availableMutations)
  • The method - the mutated method. Will be picked from the configured MutationScope
  • The Mutation parameters - depend on the created Mutation. Cannot be specified without specifiying the Mutation class. Check the 'parameters' protocols of the Mutation classes, and class-comments of these classes, for detailed information. If required, the Mutation will be asked to create random parameters.

4. Apply the Mutation

Methods of Mutation in protocol 'mutating'.

#apply - Apply the mutation (without reverting it!) The whole system will be affected by the mutation. A Mutation can only be applied once and will report an error, if applied twice.

#revert - Revert the mutation (if already applied). A Mutation object can be reused (applied again, after being reverted).

#doMutated: - Execute a block in the context of the Mutation, ensuring, that it will be reverted after the block.

5. Example code snippets

"Create a fixed Mutation for a fixed method. Execute the mutation."
(MEMutationFactory onMethodWrappers
		createMutation: MEStringLiteralMutation
		forMethod: MEMutationTestObject class -> #returnStringOne)
		doMutated: [ MEMutationTestObject returnStringOne ]
"Create a fixed Mutation for a fixed method, with fixed parameters. Execute the mutation multiple times."
(MEMutationFactory onMethodWrappers
		createMutation: MEStringLiteralMutation
		withParameters: ({ #replacementMode -> 'The Mutated String!' } as: Dictionary)
		forMethod: MEMutationTestObject class -> #returnStringOne)
		doMutated: [ MEMutationTestObject returnStringOne ];
		doMutated: [ MEMutationTestObject returnStringThree ];
		doMutated: [ MEMutationTestObject returnStringOne ]
"Create a random Mutation for a random method in a package, with random parameters etc. Print the random parameters."
mutation := (MEMutationFactory onMethodWrappers
		scope: (MEMutationScope new
			addPackage: 'MutationEngine-Tests'; yourself))
		randomMutation.
{ mutation method. mutation class. mutation parameters }

Acknowledgments

To date the following people contributed to this project:

  • Anton Gulenko
  • Michael Perscheid

Last modified 4 years ago Last modified on 11/15/2013 03:56:34 PM