public InvariantTestFunc(AbstractType type, string name, params string[] invariants) : base(type, name) { const int cnt = 10; foreach (var invariant in invariants) { var inv = invariant; inv = inv.Replace("$T", type.NameThat); // stats var vectorsThis = 0; // recognize vars while (true) { var n = "$V" + vectorsThis; if (inv.Contains(n)) { inv = inv.Replace(n, "v" + vectorsThis); ++vectorsThis; } else { break; } } // gen code var comps = type is VectorType ? ((VectorType)type).Components : 1; var code = new List <string>(); for (var _ = 0; _ < cnt; ++_) { code.Add("{"); for (var i = 0; i < vectorsThis; ++i) { var vals = type.BaseType.RandomSmallVals(comps); code.Add($" var v{i} = {type.Construct(type, vals)};"); } if (inv.Contains("==")) { var parts = inv.Split(new[] { "==" }, StringSplitOptions.None); Debug.Assert(parts.Length == 2); code.Add($" Assert.AreEqual({parts[0].Trim()}, {parts[1].Trim()});"); } else if (inv.Contains(" < ")) { var parts = inv.Split(new[] { " < " }, StringSplitOptions.None); Debug.Assert(parts.Length == 2); code.Add($" Assert.Less({parts[0].Trim()}, {parts[1].Trim()});"); } else if (inv.Contains(" <= ")) { var parts = inv.Split(new[] { " <= " }, StringSplitOptions.None); Debug.Assert(parts.Length == 2); code.Add($" Assert.LessOrEqual({parts[0].Trim()}, {parts[1].Trim()});"); } else if (inv.Contains(" > ")) { var parts = inv.Split(new[] { " > " }, StringSplitOptions.None); Debug.Assert(parts.Length == 2); code.Add($" Assert.Greater({parts[0].Trim()}, {parts[1].Trim()});"); } else if (inv.Contains(" >= ")) { var parts = inv.Split(new[] { " >= " }, StringSplitOptions.None); Debug.Assert(parts.Length == 2); code.Add($" Assert.GreaterOrEqual({parts[0].Trim()}, {parts[1].Trim()});"); } else if (inv.Contains("~")) { var parts = inv.Split(new[] { "~" }, StringSplitOptions.None); Debug.Assert(parts.Length == 2); code.Add($" Assert.That(glm.ApproxEqual({parts[0].Trim()}, {parts[1].Trim()}));"); } else { code.Add($" Assert.That({inv});"); } code.Add("}"); } Code = code; } }