private static object MakeList(Type consumedType, ConvenienceStressState state, DeterministicRandom random, int recursionDepth, int minListSize, int maxListSize) { //The Stress consumer is asking for a list of objects. This is a bit of a complicated topic. Refer to: //Reflecting on Generics - This explains how I am identifying List Generic //http://cc.msnscache.com/cache.aspx?q=72938808547333&mkt=en-US&lang=en-US&w=d704070d&FORM=CVRE7 // //From there, we need to create an instance of the requested generic, as explained here. //http://www.codeproject.com/KB/cs/ReflectGenerics.aspx //The type of objects instantiated in the list is instanceType: Type[] genericArguments = consumedType.GetGenericArguments(); Type instanceType = genericArguments[0]; //Prepare our List object list = Activator.CreateInstance(consumedType, 1); //Create a single element array as payload for adding objects to list via reflection object[] methodCallPayload = new object[1]; int count = random.Next(maxListSize - minListSize) + minListSize; for (int i = 0; i < count; i++) { //We produce an item from a differently selected factory each time. methodCallPayload[0] = MakeItem(instanceType, state, random, recursionDepth); consumedType.InvokeMember("Add", BindingFlags.InvokeMethod, null, list, methodCallPayload); } return(list); }
public Sequence GetNext(IState state, DeterministicRandom random) { Sequence sequence = null; ConvenienceStressState stressState = (ConvenienceStressState)state; Queue <Type> possibleActions = stressState.GetActions(random); while (possibleActions.Count > 0 && sequence == null) { DiscoverableAction action = (DiscoverableAction)Activator.CreateInstance(possibleActions.Dequeue()); Trace.WriteLine("[DiscoverableActionSequencer]Populating Action."); bool hasValidInputs = PopulateDiscoverableInputs(action, random, stressState, 0); //Add action to sequence only CanPerform is true, and input has been created successfully. if (hasValidInputs && action.CanPerform()) { sequence = new Sequence(); sequence.AddAction(action); } } if (sequence == null) { throw new InvalidOperationException("Stress could not find a new Action to perform at this state."); } return(sequence); }
private static object MakeItem(Type consumedType, ConvenienceStressState state, DeterministicRandom random, int recursionDepth) { //Look up a Factory supporting this type DiscoverableFactory factory = state.GetFactory(consumedType, random, FavorSimpleFactories(recursionDepth)); //Provide the factory with what it needs PopulateDiscoverableInputs(factory, random, state, recursionDepth); //Create desired type via factory return(factory.Create(consumedType, random)); }
/// <summary> /// Populates Input properties for a Factory or Action /// </summary> /// <param name="consumer">Object to be populated</param> /// <param name="random">Deterministic Random source</param> /// <param name="state">Supporting State Object</param> /// <param name="recursionLimit">Recursion depth - ie - how many parent invocations does the current code have?</param> /// <returns></returns> private static bool PopulateDiscoverableInputs(IDiscoverableObject consumer, DeterministicRandom random, ConvenienceStressState state, int recursionDepth) { List <PropertyDescriptor> inputProperties = DiscoverableInputHelper.GetInputProperties(consumer.GetType()); foreach (PropertyDescriptor property in inputProperties) { //Determine desired type Type consumedType = property.PropertyType; Object result = null; InputAttribute inputAttribute = (InputAttribute)property.Attributes[typeof(InputAttribute)]; if (inputAttribute == null) { inputAttribute = InputAttribute.CreateFromFactory; } switch (inputAttribute.ContentInputSource) { // case ContentInputSource.GetFromLogicalTree: // Factories can not consume existing objects - Only actions can do so if (consumer.GetType().IsSubclassOf(typeof(DiscoverableFactory))) { throw new InvalidOperationException("A Factory cannot consume from state"); } //Get Property from window surface Area Trace.WriteLine("[DiscoverableActionSequencer] Getting a Logical Tree Item"); result = state.GetFromLogicalTree(consumedType, random); //For object from Logical tree, null means item not found, thus failed. if (result == null) { return(false); } break; case ContentInputSource.GetFromVisualTree: // Factories can not consume existing objects - Only actions can do so if (consumer.GetType().IsSubclassOf(typeof(DiscoverableFactory))) { throw new InvalidOperationException("A Factory cannot consume from state"); } //Get Property from window surface Area Trace.WriteLine("[DiscoverableActionSequencer] Getting a Visual Tree item"); result = state.GetFromVisualTree(consumedType, random); //For object from Visual tree, null result means item not found, thus failed. if (result == null) { return(false); } break; case ContentInputSource.GetWindowListFromState: // Factories can not consume existing objects - Only actions can do so if (consumer.GetType().IsSubclassOf(typeof(DiscoverableFactory))) { throw new InvalidOperationException("A Factory cannot consume from state"); } Trace.WriteLine("[DiscoverableActionSequencer] Getting WindowList property of state"); result = state.WindowList; break; //Populate data from Type.Property specific constraints system // case ContentInputSource.CreateFromConstraints: Trace.WriteLine("[DiscoverableActionSequencer] Getting a Constraint based item"); result = state.MakeFromConstraint(consumer.GetType(), property.Name, random); break; case ContentInputSource.GetFromObjectTree: Trace.WriteLine("[DiscoverableActionSequencer] Getting a object from Object tree."); result = state.GetFromObjectTree(consumedType, random); //For object from Object tree, null result means item not found, thus failed. if (result == null) { return(false); } break; //Default behavior is to produce content from factories default: if (recursionDepth < standardRecursionLimit || (recursionDepth < absoluteRecursionLimit && inputAttribute.IsEssentialContent)) { Trace.WriteLine("[DiscoverableActionSequencer] Producing factory content"); //Basic workflow for producing Factory content if (!consumedType.IsGenericType) { result = MakeItem(consumedType, state, random, recursionDepth + 1); } else { if (consumedType.GetGenericTypeDefinition() == typeof(List <>)) { result = MakeList(consumedType, state, random, recursionDepth + 1, inputAttribute.MinListSize, inputAttribute.MaxListSize); } else { throw new InvalidOperationException("We can't work with this type yet:. " + consumedType.GetGenericTypeDefinition()); } } } else if (recursionDepth >= absoluteRecursionLimit && inputAttribute.IsEssentialContent) { throw new InvalidOperationException("The stress test factory has reached the absolute recursion limit and is still demanding essential content. Is there a cyclic chain only involving factories requiring their inputs?"); } else //Factory Recursion depth exceeded. We are leaving non-essential property null { //No Operation } break; } //Set value to desired input property.SetValue(consumer, result); if (result != null) { Trace.WriteLine(String.Format("[DiscoverableActionSequencer] Provided a [{0}] of type {1} for {2}", result, result.GetType(), consumer)); } else { Trace.WriteLine(String.Format("[DiscoverableActionSequencer] Provided a null for {1}", result, consumer)); } } return(true); }