Beispiel #1
0
        /// <summary> Deserialization implementation. </summary>
        public override bool Deserialize(XElement elem, ITypeData t, Action <object> setter)
        {
            if (t.DescendsTo(typeof(IDynamicStep)) == false)
            {
                return(false);
            }

            try
            {
                IDynamicStep step = (IDynamicStep)t.CreateInstance(Array.Empty <object>());
                Serializer.Register(step);

                TryDeserializeObject(elem, TypeData.GetTypeData(step), setter, step, logWarnings: false);

                ITestStep genStep = step.GetStep();
                bool      res     = true;
                if (elem.IsEmpty == false)
                {
                    res = TryDeserializeObject(elem, TypeData.GetTypeData(genStep), setter, genStep, logWarnings: false);
                }
                else
                {
                    setter(genStep);
                }
                Serializer.GetSerializer <TestStepSerializer>().FixupStep(genStep, true);
                return(res);
            }
            catch (Exception e)
            {
                Log.Error("Unable to deserialize step of type {0}. Error was: {1}", t, e.Message);

                Log.Debug(e);
                return(true);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Constructs a new instance of the object represented by the expression.
        /// </summary>
        /// <param name="expression">json object expression</param>
        /// <param name="deserializer">deserializer for deserializing constructor arguments if any</param>
        /// <returns>constructed, but unpopulated object</returns>
        protected virtual object ConstructObject(ObjectExpression expression, IDeserializerHandler deserializer)
        {
            ITypeData handler = Settings.Types[expression.ResultType];

            // set the default type if none set
            if (expression.ConstructorArguments.Count > 0)
            {
                // old way expects parameters in the constructor list
                ResolveConstructorTypes(Settings, expression);
            }
            else
            {
                foreach (IPropertyData parameter in handler.ConstructorParameters)
                {
                    int propLocation = expression.IndexOf(parameter.Alias);
                    if (propLocation >= 0)
                    {
                        Expression arg = expression.Properties[propLocation].ValueExpression;
                        arg.ResultType = parameter.PropertyType;
                        expression.ConstructorArguments.Add(arg);
                        expression.Properties.RemoveAt(propLocation);
                    }
                    else
                    {
                        expression.ConstructorArguments.Add(new NullExpression());
                    }
                }
            }

            object[] args = new object[expression.ConstructorArguments.Count];

            for (int i = 0; i < args.Length; i++)
            {
                Expression carg = expression.ConstructorArguments[i];
                if (i < handler.ConstructorParameters.Count && handler.ConstructorParameters[i].HasConverter)
                {
                    TypeConverterExpressionHandler converterHandler = (TypeConverterExpressionHandler)Settings.ExpressionHandlers.Find(typeof(TypeConverterExpressionHandler));
                    args[i] = converterHandler.Evaluate(carg, deserializer, handler.ConstructorParameters[i].TypeConverter);
                }
                else
                {
                    args[i] = deserializer.Evaluate(carg);
                }
            }
            object result = handler.CreateInstance(args);

            expression.OnObjectConstructed(result);
            return(result);
        }
 public object CreateInstance(object[] arguments)
 {
     return(innerType.CreateInstance(arguments));
 }
Beispiel #4
0
        public static int Execute(params string[] args)
        {
            // Trigger plugin manager before anything else.
            if (ExecutorClient.IsRunningIsolated)
            {
                // TODO: This is not needed right now, but might be again when we fix the TODO in tap.exe
                //PluginManager.DirectoriesToSearch.Clear();
                //PluginManager.DirectoriesToSearch.Add(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
                using (var tpmClient = new ExecutorClient())
                {
                    tpmClient.MessageServer("delete " + Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
                }
            }

            // Set TapMutex to ensure any installers know about running OpenTAP processes.
            ReflectionHelper.SetTapMutex();

            try
            {
                // Turn off the default system behavior when CTRL+C is pressed.
                // When Console.TreatControlCAsInput is false, CTRL+C is treated as an interrupt instead of as input.
                Console.TreatControlCAsInput = false;
            }
            catch { }
            try
            {
                var execThread = TapThread.Current;
                Console.CancelKeyPress += (s, e) =>
                {
                    e.Cancel = true;
                    execThread.Abort();
                };
            }
            catch { }

            CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;

            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            // Find the called action
            if (!TypeData.GetDerivedTypes <ICliAction>().Any())
            {
                Console.WriteLine("No commands found. Please try reinstalling OpenTAP.");
                return(1);
            }

            try
            {
                // setup logging to be relative to the executing assembly.
                // at this point SessionLogs.Initialize has already been called (PluginManager.Load).
                // so the log is already being saved at a different location.
                var  logpath      = EngineSettings.Current.SessionLogPath.Expand(date: Process.GetCurrentProcess().StartTime);
                bool isPathRooted = Path.IsPathRooted(logpath);
                if (isPathRooted == false)
                {
                    var dir = Path.GetDirectoryName(typeof(SessionLogs).Assembly.Location);
                    if (ExecutorClient.IsRunningIsolated)
                    {
                        // redirect the isolated log path to the non-isolated path.
                        dir = ExecutorClient.ExeDir;
                    }

                    logpath = Path.Combine(dir, logpath);
                }

                SessionLogs.Rename(logpath);
            }
            catch (Exception e)
            {
                log.Error("Path defined in Engine settings contains invalid characters: {0}", EngineSettings.Current.SessionLogPath);
                log.Debug(e);
            }

            ITypeData selectedCommand = null;

            // Find selected command
            var actionTree  = new CliActionTree();
            var selectedcmd = actionTree.GetSubCommand(args);

            if (selectedcmd?.Type != null && selectedcmd?.SubCommands.Any() != true)
            {
                selectedCommand = selectedcmd.Type;
            }
            void print_command(CliActionTree cmd, int level, int descriptionStart)
            {
                if (cmd.IsBrowsable)
                {
                    int relativePadding = descriptionStart - (level * LevelPadding); // Calculate amount of characters to pad right before description start to ensure description alignments.
                    Console.Write($"{"".PadRight(level * LevelPadding)}{cmd.Name.PadRight(relativePadding)}");
                    if (cmd.Type?.IsBrowsable() ?? false)
                    {
                        Console.WriteLine($"{cmd.Type.GetDisplayAttribute().Description}");
                    }
                    else
                    {
                        Console.WriteLine();
                    }

                    if (cmd.IsGroup)
                    {
                        foreach (var subCmd in cmd.SubCommands)
                        {
                            print_command(subCmd, level + 1, descriptionStart);
                        }
                    }
                }
            }

            // Print default info
            if (selectedCommand == null)
            {
                Console.WriteLine("OpenTAP Command Line Interface ({0})", Assembly.GetExecutingAssembly().GetSemanticVersion().ToString(4));
                Console.WriteLine("Usage: tap <command> [<subcommand(s)>] [<args>]\n");

                if (selectedcmd == null)
                {
                    Console.WriteLine("Valid commands are:");
                    foreach (var cmd in actionTree.SubCommands)
                    {
                        print_command(cmd, 0, actionTree.GetMaxCommandTreeLength(LevelPadding) + LevelPadding);
                    }
                }
                else
                {
                    Console.Write("Valid subcommands of ");
                    print_command(selectedcmd, 0, actionTree.GetMaxCommandTreeLength(LevelPadding) + LevelPadding);
                }

                Console.WriteLine($"\nRun \"{(OperatingSystem.Current == OperatingSystem.Windows ? "tap.exe" : "tap")} " +
                                  "<command> [<subcommand>] -h\" to get additional help for a specific command.\n");

                if (args.Length == 0 || args.Any(s => s.ToLower() == "--help" || s.ToLower() == "-h"))
                {
                    return(0);
                }
                else
                {
                    return(-1);
                }
            }

            if (selectedCommand != TypeData.FromType(typeof(RunCliAction)) && UserInput.Interface == null) // RunCliAction has --non-interactive flag and custom platform interaction handling.
            {
                CliUserInputInterface.Load();
            }

            ICliAction packageAction = null;

            try{
                packageAction = (ICliAction)selectedCommand.CreateInstance();
            }catch (TargetInvocationException e1) when(e1.InnerException is System.ComponentModel.LicenseException e)
            {
                Console.Error.WriteLine("Unable to load CLI Action '{0}'", selectedCommand.GetDisplayAttribute().GetFullName());
                Console.Error.WriteLine(e.Message);
                return(-4);
            }

            if (packageAction == null)
            {
                Console.WriteLine("Error instantiating command {0}", selectedCommand.Name);
                return(-3);
            }

            try
            {
                int skip = selectedCommand.GetDisplayAttribute().Group.Length + 1; // If the selected command has a group, it takes two arguments to use the command. E.g. "package create". If not, it only takes 1 argument, E.g. "restapi".
                return(packageAction.Execute(args.Skip(skip).ToArray()));
            }
            catch (ExitCodeException ec)
            {
                log.Error(ec.Message);
                return(ec.ExitCode);
            }
            catch (ArgumentException ae)
            {
                // ArgumentException usually contains several lines.
                // Only print the first line as an error message.
                // Example message:
                //  "Directory is not a git repository.
                //   Parameter name: repositoryDir"
                var lines = ae.Message.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                log.Error(lines.First());
                for (int i = 1; i < lines.Length; i++)
                {
                    log.Debug(lines[i]);
                }
                return(-1);
            }
            catch (OperationCanceledException ex)
            {
                log.Error(ex.Message);
                return(1);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                log.Debug(ex);
                return(-1);
            }
            finally
            {
                Log.Flush();
            }
        }
Beispiel #5
0
        /// <summary>
        /// Tries to deserialize an object from an XElement.
        /// </summary>
        /// <param name="element"></param>
        /// <param name="t"></param>
        /// <param name="setter"></param>
        /// <param name="newobj"></param>
        /// <param name="logWarnings">Whether warning messages should be emitted in case of missing properties.</param>
        /// <returns>True on success.</returns>
        public virtual bool TryDeserializeObject(XElement element, ITypeData t, Action <object> setter, object newobj = null, bool logWarnings = true)
        {
            if (element.IsEmpty && !element.HasAttributes)
            {
                setter(null);
                return(true);
            }
            if (newobj == null)
            {
                try
                {
                    newobj = t.CreateInstance(Array.Empty <object>());
                    t      = TypeData.GetTypeData(newobj);
                }
                catch (TargetInvocationException ex)
                {
                    if (ex.InnerException is System.ComponentModel.LicenseException)
                    {
                        throw new Exception(string.Format("Could not create an instance of '{0}': {1}", t.GetAttribute <DisplayAttribute>().Name, ex.InnerException.Message));
                    }
                    else
                    {
                        ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                    }
                }
            }

            var prevobj = Object;

            Object = newobj;
            var t2 = t;

            if (newobj == null)
            {
                throw new ArgumentNullException(nameof(newobj));
            }
            var properties = t2.GetMembers()
                             .Where(x => x.HasAttribute <XmlIgnoreAttribute>() == false)
                             .ToArray();

            try
            {
                foreach (var prop in properties)
                {
                    var attr = prop.GetAttribute <XmlAttributeAttribute>();
                    if (attr == null)
                    {
                        continue;
                    }
                    var name       = string.IsNullOrWhiteSpace(attr.AttributeName) ? prop.Name : attr.AttributeName;
                    var attr_value = element.Attribute(XmlConvert.EncodeLocalName(name));
                    var p          = prop as MemberData;

                    if (p != null && attr_value != null && p.Member is PropertyInfo csprop)
                    {
                        try
                        {
                            readContentInternal(csprop.PropertyType, false, () => attr_value.Value, element, out object value);

                            p.SetValue(newobj, value);
                        }
                        catch (Exception e)
                        {
                            if (logWarnings)
                            {
                                Log.Warning(element, "Attribute value '{0}' was not read correctly as a {1}", attr_value.Value, p);
                                Log.Debug(e);
                            }
                        }
                    }
                }

                if (properties.FirstOrDefault(x => x.HasAttribute <XmlTextAttribute>()) is IMemberData mem2)
                {
                    object value;
                    if (mem2.TypeDescriptor is TypeData td &&
                        readContentInternal(td.Load(), false, () => element.Value, element, out object _value))
                    {
                        value = _value;
                    }
                    else
                    {
                        value = StringConvertProvider.FromString(element.Value, mem2.TypeDescriptor, null);
                    }
                    mem2.SetValue(newobj, value);
                }
                else
                {
                    var    props    = properties.ToLookup(x => x.GetAttributes <XmlElementAttribute>().FirstOrDefault()?.ElementName ?? x.Name);
                    var    elements = element.Elements().ToArray();
                    bool[] visited  = new bool[elements.Length];

                    double order = 0;
                    int    foundWithCurrentType = 0;
                    while (true)
                    {
                        double nextOrder = 1000;
                        // since the object might be dynamically adding properties as other props are added.
                        // we need to iterate a bit. Example: Test Plan Reference.

                        int found = visited.Count(x => x);
                        for (int i = 0; i < elements.Length; i++)
                        {
                            var element2 = elements[i];
                            if (visited[i])
                            {
                                continue;
                            }
                            if (element2.Attribute(IgnoreMemberXName) is XAttribute attr && attr.Value == "true")
                            {
                                visited[i] = true;
                                continue;
                            }
                            IMemberData property        = null;
                            var         name            = XmlConvert.DecodeName(element2.Name.LocalName);
                            var         propertyMatches = props[name];

                            int hits = 0;
                            foreach (var p in propertyMatches)
                            {
                                if (p.Writable || p.HasAttribute <XmlIgnoreAttribute>())
                                {
                                    property = p;
                                    hits++;
                                }
                            }

                            if (0 == hits)
                            {
                                try
                                {
                                    if (property == null)
                                    {
                                        property = t2.GetMember(name);
                                    }
                                    if (property == null)
                                    {
                                        property = t2.GetMembers().FirstOrDefault(x => x.Name == name);
                                    }
                                }
                                catch { }
                                if (property == null || property.Writable == false)
                                {
                                    continue;
                                }
                                hits = 1;
                            }
                            if (hits > 1)
                            {
                                Log.Warning(element2, "Multiple properties named '{0}' are available to the serializer in '{1}' this might give issues in serialization.", element2.Name.LocalName, t.GetAttribute <DisplayAttribute>().Name);
                            }

                            if (property.GetAttribute <DeserializeOrderAttribute>() is DeserializeOrderAttribute orderAttr)
                            {
                                if (order < orderAttr.Order)
                                {
                                    if (orderAttr.Order < nextOrder)
                                    {
                                        nextOrder = orderAttr.Order;
                                    }
                                    continue;
                                }
                            }
                            else
                            {
                                nextOrder = order;
                            }

                            visited[i] = true;
                            var prev = CurrentMember;
                            CurrentMember = property;
                            try
                            {
                                if (CurrentMember.HasAttribute <XmlIgnoreAttribute>())      // This property shouldn't have been in the file in the first place, but in case it is (because of a change or a bug), we shouldn't try to set it. (E.g. SweepLoopRange.SweepStep)
                                {
                                    if (!CurrentMember.HasAttribute <BrowsableAttribute>()) // In the special case we assume that this is some compatibility property that still needs to be set if present in the XML. (E.g. TestPlanReference.DynamicDataContents)
                                    {
                                        continue;
                                    }
                                }

                                if (property is MemberData mem && mem.Member is PropertyInfo Property && Property.PropertyType.HasInterface <IList>() && Property.PropertyType.IsGenericType && Property.HasAttribute <XmlElementAttribute>())
                                {
                                    // Special case to mimic old .NET XmlSerializer behavior
                                    var             list     = (IList)Property.GetValue(newobj);
                                    Action <object> setValue = x => list.Add(x);
                                    Serializer.Deserialize(element2, setValue, Property.PropertyType.GetGenericArguments().First());
                                }
                                else
                                {
                                    Action <object> setValue = x =>
                                    {
                                        var current = property.GetValue(newobj);
                                        property.SetValue(newobj, x);
                                        if (false == Equals(current, x))
                                        { // for some value-like type, it may be needed
                                            // to set the parent object when a property is changed
                                            // example: complex test plan parameters.
                                            setter(newobj);
                                        }
                                    };
                                    Serializer.Deserialize(element2, setValue, property.TypeDescriptor);
                                }
                            }
Beispiel #6
0
 public object CreateInstance(object[] arguments)
 {
     return(InnerDescriptor.CreateInstance(arguments));
 }
 /// <summary>
 /// Creates an instance of this type using the default constructor.
 /// </summary>
 public static object CreateInstance(this ITypeData type)
 {
     return(type.CreateInstance(Array.Empty <object>()));
 }