Skip to content

Instantly share code, notes, and snippets.

@bbarry
Created January 24, 2017 22:36
Show Gist options
  • Save bbarry/0b13578aad0379e3171dd5dc7d50af5b to your computer and use it in GitHub Desktop.
Save bbarry/0b13578aad0379e3171dd5dc7d50af5b to your computer and use it in GitHub Desktop.
[Fact(Skip = "This test generator is capable of producing crashes that are not yet fixed; see, for example, Fuzz5815")]
public void Fuzz()
{
int dt = Math.Abs(new DateTime().Ticks.GetHashCode() % 10000000);
// generate a pattern-matching switch randomly from templates
string[] expressions = new[]
{
"M", // a method group
"(() => 1)", // a lambda expression
"1", // a constant
"2", // a constant
"null", // the null constant
"default(int?)", // a null constant of type int?
"((int?)1)", // a constant of type int?
"M()", // a method invocation
"double.NaN", // a scary constant
"1.1", // a double constant
"NotFound" // an unbindable expression
};
string[] types = new[]
{
"object",
"var",
"int",
"int?",
"double",
"string",
"NotFound"
};
// include casted method calls of the provided types
expressions = types.Select(t => "((" + t + ")M())").Concat(expressions).ToArray();
// forms:
// {expression}
// {type} x{0-9}
// {type} _
string[] patterns = expressions
.Concat(types.SelectMany(t => Enumerable.Range(0, 10).Select(i => t + " x" + i)))
.Concat(types.Select(t => t + " _"))
.ToArray();
for (int i = 1; i < 100000; i++)
{
PatternMatchingFuzz(i + dt, expressions, patterns);
}
}
public void PatternMatchingFuzz(int dt, string[] expressions, string[] patterns)
{
Random r = new Random(dt);
string Expression() => expressions[r.Next(expressions.Length)];
string Pattern() => patterns[r.Next(patterns.Length)];
const string body = @"
public class Program{0}
{{
public static void Main(string[] args)
{{
{1}
}}
private static object M() => null;
}}";
var statement = new StringBuilder();
switch (r.Next(2))
{
case 0:
// test the "is-pattern" expression
statement.AppendFormat("if ({0} is {1}) {{}}", Expression(), Pattern());
break;
case 1:
// test the pattern switch statement
statement.AppendFormat("switch ({0})\n{{\n", Expression());
var nCases = r.Next(5);
for (int i = 1; i <= nCases; i++)
{
statement.AppendFormat(" case {0}:\n", Pattern());
if (i == nCases || r.Next(2) == 0)
{
statement.AppendLine(" break;");
}
}
statement.AppendLine("}");
break;
default:
throw null;
}
var program = string.Format(body, dt, statement);
CreateCompilationWithMscorlib45(program).GetDiagnostics();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment