private void CheckMethods(HashSet <string> obtainedMembers) { IEnumerable <MethodInfo> methods = typeof(Res).GetMethods(BindingFlags.Static | BindingFlags.NonPublic).Where(m => m.IsAssembly); var generateSettings = new GenerateObjectSettings { AllowCreateObjectWithoutConstructor = true }; // for PropertyDescriptors foreach (MethodInfo mi in methods) { var method = mi.IsGenericMethodDefinition ? mi.MakeGenericMethod(random.NextObject(typeof(Enum)).GetType()) : mi; object[] parameters = method.GetParameters().Select(p => random.NextObject(p.ParameterType, generateSettings)).ToArray(); string value = method.Invoke(null, parameters).ToString(); Assert.IsTrue(!value.StartsWith(unavailableResourcePrefix, StringComparison.Ordinal), $"{nameof(Res)}.{method.Name} refers to an undefined resource."); Assert.IsTrue(!value.StartsWith(invalidResourcePrefix, StringComparison.Ordinal), $"{nameof(Res)}.{method.Name} uses too few parameters."); for (int i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; Assert.IsTrue(value.Contains(parameter.ToString(), StringComparison.Ordinal) //|| mi.IsGenericMethodDefinition // Xxx<TEnum>(TEnum value) - not value but possible TValue is printed //|| parameter is float f && value.Contains(f.ToString("P2"), StringComparison.Ordinal) // percentage format of float //|| parameter is double d && value.ContainsAny(StringComparison.Ordinal, d.ToString("N2"), d.ToString("P2")) // double: percentage or number //|| parameter is bool b && value.Contains(b ? PublicResources.Yes : PublicResources.No, StringComparison.Ordinal) // percentage format of float //|| parameter is int n && value.Contains(n.ToString("N0"), StringComparison.Ordinal) // normal ToString checked above, number format checked here //|| parameter is long l && value.Contains(l.ToString("N0"), StringComparison.Ordinal), // normal ToString checked above, number format checked here , $"{nameof(Res)}.{method.Name} does not use parameter #{i}."); } obtainedMembers.Add(method.Name); } }
public void NextObjectTest() { var rnd = new Random(); void Test <T>(GenerateObjectSettings settings = null) { var obj = rnd.NextObject <T>(settings); // Console.WriteLine($"Random {typeof(T).Name}: {obj}"); } // native types Test <bool>(); Test <byte>(); Test <sbyte>(); Test <char>(); Test <short>(); Test <ushort>(); Test <int>(); Test <uint>(); Test <long>(); Test <ulong>(); Test <float>(); Test <double>(); Test <decimal>(); Test <string>(); Test <StringBuilder>(); Test <Uri>(); Test <Guid>(); Test <DateTime>(); Test <DateTimeOffset>(); Test <TimeSpan>(); Test <IntPtr>(); Test <UIntPtr>(); Test <byte?>(); // enums Test <EmptyEnum>(); Test <ConsoleColor>(); Test <Enum>(); // arrays Test <byte[]>(); Test <byte?[]>(); Test <byte[, ]>(); // collections Test <List <int> >(); // populate Test <Dictionary <int, string> >(); // populate Test <ArrayList>(); // populate Test <Hashtable>(); // populate Test <BitArray>(); // array ctor Test <ReadOnlyCollection <int> >(); // IList<T> ctor Test <ArraySegment <int> >(); // array ctor Test <Cache <int, int> >(); // populate Test <Queue>(); // ICollection ctor #if !(NETCOREAPP2_0 || NETCOREAPP3_0) Test <CounterCreationDataCollection>(new GenerateObjectSettings { SubstitutionForObjectType = typeof(CounterCreationData) }); // populate, typed object #endif // key-value Test <DictionaryEntry>(); Test <KeyValuePair <int, string> >(); // reflection types Test <Assembly>(); Test <Type>(); Test <MethodBase>(); Test <MemberInfo>(); // base types var cfg = new GenerateObjectSettings { AllowDerivedTypesForNonSealedClasses = true }; Test <EventArgs>(cfg); // abstract types/interfaces Test <Enum>(); Test <IConvertible>(); // delegates Test <Delegate>(); Test <MulticastDelegate>(); Test <Func <int> >(); Test <OutDelegate>(); // recursive types Test <Recursive>(); // contains self as member Test <RecursiveCollection>(); // contains self as collection item Test <XmlSchemaObject>(); // contains self as abstract class }