/// <summary> /// Creates a doOnce context instruction. /// </summary> /// <param name="xn">The XML repersentation of the instruction to be checked</param> /// <param name="con">The current context object</param> static DoOnceContext CreateDoOnceContext(XmlNode xn, Context con) { string maxWait = XmlFiler.getAttribute(xn, "until"); // Assert.IsTrue(maxWait == null || maxWait.Length == 0, "Do-Once context must have an until attribute."); Logger.getOnly().isNotNull(maxWait, "Do-Once context must have an until attribute."); Logger.getOnly().isTrue(maxWait != "", "Do-Once context must have a non-empty 'until' attribute."); DoOnceContext doOnce = new DoOnceContext(Convert.ToInt32(maxWait)); doOnce.WaitingFor = XmlFiler.getAttribute(xn, "waiting-for"); doOnce.OnPass = XmlFiler.getAttribute(xn, "on-pass"); doOnce.OnFail = XmlFiler.getAttribute(xn, "on-fail"); doOnce.ModelNode = con.ModelNode; AddInstruction(xn, doOnce, con); /* foreach (XmlNode xnChild in xn.ChildNodes) * { * InterpretChild(xnChild, doOnce); * } */ return(doOnce); }
/// <summary> /// Creates and parses a condition. /// </summary> /// <param name="xn">The XML repersentation of the instruction to be checked</param> /// <returns>A Condition intsruction</returns> static Condition CreateCondition(XmlNode xn) { Condition cond = new Condition(); cond.Of = XmlFiler.getAttribute(xn, "of"); // can be an id, 'literal' or number Logger.getOnly().isNotNull(cond.Of, "Condition must have an 'of' attribute."); Logger.getOnly().isTrue(cond.Of != "", "Condition must have a non-null 'of' attribute."); cond.Is = XmlFiler.getAttribute(xn, "is"); // can be equal, true, false, 'literal' or number Logger.getOnly().isNotNull(cond.Is, "Condition must have an 'is' attribute."); Logger.getOnly().isTrue(cond.Is != "", "Condition must have a non-null 'is' attribute."); cond.To = XmlFiler.getAttribute(xn, "to"); // can be an id, 'literal' or number foreach (XmlNode condElt in xn.ChildNodes) { switch (condElt.Name) { case "condition": Condition condChild = CreateCondition(condElt); cond.AddCondition(condChild); break; } } return(cond); }
/// <summary> /// Creates and parses a message contained in some instructions. /// </summary> /// <param name="ins"></param> /// <param name="body"></param> protected void InterpretMessage(XmlNodeList body) { if (body != null) { Message message = new Message(); foreach (XmlNode node in body) { switch (node.Name) { case "#text": // a nameless text node message.AddText(node.Value); break; case "data": message.AddDataRef(XmlFiler.getAttribute(node, "of"), this); break; case "beep": message.AddSound(new Beep()); break; case "sound": string frequency = XmlFiler.getAttribute(node, "frequency"); string duration = XmlFiler.getAttribute(node, "duration"); m_log.isTrue(frequency != null && duration != null, makeNameTag() + "Sound instruction must have a frequency and duration."); Sound sound = null; try { sound = new Sound(Convert.ToUInt32(frequency), Convert.ToUInt32(duration)); } catch { m_log.fail(makeNameTag() + "Sound instruction must have a frequency and duration in milliseconds."); } message.AddSound(sound); break; } } Message = message; } }
// look for the expected dialog to appear. If it does, make an accessibilty // helper for it. public override void Execute() { // base.Execute(ts); // can't call this yet as it executes the children Wait(); // do call this but make sure Rest is reset to zero! Rest = 0; // reset to zero so there is no delay after the dialog is found. // number is needed in diagnostics for the log if (Number == -1) { Number = TestState.getOnly().IncInstructionCount; } Process proc = Application.Process; /// If present, use the selected dialog model title Context con = (Context)Ancestor(typeof(Context)); if (m_select != null && m_select != "") { // make a new model context node and move dialog's children to it XmlDocument doc = m_elt.OwnerDocument; XmlElement modElt = doc.CreateElement("model"); modElt.SetAttribute("select", m_select); XmlNodeList children = m_elt.ChildNodes; int count = children.Count; while (count > 0) { // move dialog children to model XmlNode child = children.Item(0); //get the first child modElt.AppendChild(child); // automatically removed from m_elt!! count = children.Count; } m_elt.AppendChild(modElt); // set the title to look for // can only have one text node XmlNodeList pathNodes = XmlInstructionBuilder.selectNodes(this, m_select, makeName()); m_log.isNotNull(pathNodes, "dialog " + this.Id + " select='" + m_select + "' returned no model"); m_log.isTrue(pathNodes.Count > 0, "dialog " + this.Id + " select='" + m_select + "' returned no model nodes"); // This is the model node XmlNode modNode = pathNodes.Item(0); m_title = XmlFiler.getAttribute(modNode, "title"); m_name = XmlFiler.getAttribute(modNode, "name"); m_select = null; // can only do this one time in do-once or model } if (m_title != null && m_title != "") { m_title = Utilities.evalExpr(m_title); } if (m_name != null && m_name != "") { m_name = Utilities.evalExpr(m_name); } m_log.paragraph(image()); // Give the window m_Rest seconds to show up int startTick = System.Environment.TickCount; IntPtr foundHwndPtr; string name = null; while (!m_found) { // If there is a regular expression, try it. if (m_title != null && m_title.StartsWith("rexp#")) { // match the window title via the regular expression Process[] allProcs = Process.GetProcesses(); Regex rx = null; try { rx = new Regex(m_title.Substring(5)); } catch (ArgumentException e) { m_log.paragraph("on-dialog title from rexp# " + m_title.Substring(5) + " error: " + e.Message); break; } for (int p = 0; p < allProcs.Length; p++) { Process pro = allProcs[p]; AccessibilityHelper ah = new AccessibilityHelper(pro.Handle); if (rx.IsMatch(ah.Name)) { m_ah = ah; m_found = true; break; } } } else { // get the window handle for windows with the right name // unfortuneately, other windows, or partially formed windows // seem to be obtained too. foundHwndPtr = FindWindow(null, m_title); if ((int)foundHwndPtr != 0) { // is this the window? Is it completely formed? m_ah = new AccessibilityHelper(foundHwndPtr); if (m_ah == null) { m_log.paragraph("Obtained window with no Accessibiilty!"); } else // this window has accessibility - hope it's fully built { // is this or one of its children the window? name = m_ah.Name; //when name1 = "", m_ah is probably bad - i.e. not an object if (name == "") { } // do nothing, keep looking else if (name.Equals(m_title) || name.Equals(this.m_name)) { // this is likely it m_found = true; } else // m_ah might be the ah for the main app or dialog window { // Maybe one of its children is the window we want m_ah = m_ah.FindChild(m_title, AccessibleRole.Dialog); if (m_ah != null) { // is this the window? name = m_ah.Name; // name1 can't be null if (name == "") { } // do nothing, keep looking else if (name.Equals(m_title) || name.Equals(this.m_name)) { // this might be it m_found = true; } } } } } } if (Utilities.NumTicks(startTick, System.Environment.TickCount) > m_until) { break; // time is up } System.Threading.Thread.Sleep(100); } m_Rest = 0; // don't wait later when base.Execute is invoked if (m_found) { m_DlgHwndStack.Push(m_ah.HWnd); } else { // Didn't find the window m_ah = null; } string contextPass, contextFail; PassFailInContext(OnPass, OnFail, out contextPass, out contextFail); // out m_onPass, out m_onFail); m_log.paragraph("on-dialog: passIn=" + OnPass + " failIn=" + OnFail + " pass="******" fail=" + contextFail); if (!m_found && contextFail == "skip") { return; // quietly exit } isTrue(m_found, "Dialog '" + m_title + @"' was not created or not accessible"); if (name == null) { m_log.paragraph("Wierd: ah exists but name was null - should NEVER happen!!"); name = ""; } if (contextPass == "assert") { fail("Dialog '" + m_title + "' was not supposed to display."); } base.Execute(); m_log.result(this); base.Finished = true; // finished processing this dialog context m_DlgHwndStack.Pop(); if (m_DlgHwndStack.Count > 0) { int hwnd = (int)m_DlgHwndStack.Peek(); SIL.FieldWorks.Common.Utils.Win32.SendMessage((IntPtr)hwnd, (int)SIL.FieldWorks.Common.Utils.Win32.WinMsgs.WM_SETFOCUS, 0, 0); m_log.paragraph("Sent Focus message to containing context object"); // m_ah.Parent.SendWindowMessage((int)SIL.FieldWorks.Common.Utils.Win32.WinMsgs.WM_SETFOCUS,0,0); } }
/// <summary> /// Creates a variable to be referenced by other instruction attributes. /// </summary> /// <param name="xn">The XML repersentation of the instruction to be checked</param> /// <param name="con">The current context object</param> public static Var CreateVar(XmlNode xn, Context con) { Var var = new Var(); var.Id = XmlFiler.getAttribute(xn, "id"); Logger.getOnly().isNotNull(var.Id, "Var instruction must have a id."); Logger.getOnly().isTrue(var.Id != "", "Var instruction must have a non-empty id."); string s = XmlFiler.getAttribute(xn, "set"); // select should be move to var.execute so it is dynamic! string select = XmlFiler.getAttribute(xn, "select"); if (select != null && select != "") { // the variable can only have one text node or one other node assigned to it. XmlNodeList pathNodes = selectNodes(con, select, "var" + var.Id); Logger.getOnly().isNotNull(pathNodes, "var " + var.Id + " select='" + select + "' returned no result"); if (pathNodes.Count > 0) { // append first node to set string XmlNode modNode = pathNodes.Item(0); // which property of the node to get? string prop = null; string propName = XmlFiler.getAttribute(xn, "prop"); if (propName == null && modNode is XmlElement) { propName = "path"; } if (propName == null) { propName = "value"; } if (propName != null && propName == "value") { prop = XmlPath.ResolveModelPath(modNode, modNode.Value); } if (propName != null && propName == "name") { prop = modNode.Name; } if (propName != null && propName == "type") { prop = modNode.NodeType.ToString(); } if (propName != null && propName == "path") { XmlPath xp = new XmlPath(modNode); if (xp.isValid()) { prop = xp.Path; } else { prop = null; } } s += prop; } else { s += "#NoSelection#"; } } var.Set = s; string when = XmlFiler.getAttribute(xn, "when"); string add = XmlFiler.getAttribute(xn, "add"); if (add != null) { var.Add = add; } if (var.Set == null && when == null) { // if there is a select/when then don't complain if the select found nothing Logger.getOnly().isNotNull(var.Add, "Var " + var.Id + @" set, select or add must result in a string or number value unless when=""exists"" is set."); if (select != null && select != "") { var.Set = @"#not-" + when + @"#"; } } string exists = XmlFiler.getAttribute(xn, "file-exists"); if (exists != null) { var.FileExists = exists; } string rest = XmlFiler.getAttribute(xn, "wait"); if (rest != null) { var.Rest = Convert.ToInt32(rest); } AddInstruction(xn, var, con); return(var); }
// When used in a do-once instruction, this call is repeated. // Note the code that keeps m_select from being prepended to m_path more than once. public override void Execute() { base.Execute(); if (m_path != null && m_path == "") { m_path = null; } if (m_select != null && m_select == "") { m_select = null; } if (m_selectPath != null && m_selectPath == "") { m_selectPath = null; } if (m_names != null && m_names == "") { m_names = null; } // must have: // one of select or names to provide a list to check against // with names, one of path or selectPath to get the place to check in the GUI m_log.isTrue(m_select != null || m_names != null, makeNameTag() + " must have a 'names' or 'select' attribute."); if (m_names != null) { m_log.isTrue(m_path != null || m_selectPath != null, makeNameTag() + " must have a 'path' or 'selectPath' attribute with 'names'."); } Context con = (Context)Ancestor(typeof(Context)); m_log.isNotNull(con, makeNameTag() + " must occur in some context"); m_path = Utilities.evalExpr(m_path); m_selectPath = Utilities.evalExpr(m_selectPath); m_select = Utilities.evalExpr(m_select); // set the gui path from path or select if (m_select != null && !m_doneOnce) { // set m_names and possibly m_path m_log.paragraph(makeNameTag() + " creating selection targets via " + m_select); XmlNodeList pathNodes = Instructionator.selectNodes(con, m_select, makeNameTag()); m_log.isNotNull(pathNodes, makeNameTag() + " select='" + m_select + "' returned no model node"); // The @select text may have selected a string that is itself xPath! // If so, select on that xPath if (pathNodes.Count == 1 && pathNodes.Item(0).NodeType == XmlNodeType.Text) { // this text node should be an xpath statement string xPathImage = pathNodes.Item(0).Value; m_log.paragraph(makeNameTag() + " selected a text node with more XPATH: " + xPathImage); pathNodes = Instructionator.selectNodes(con, xPathImage, makeNameTag() + " selecting " + xPathImage); m_log.isNotNull(pathNodes, makeNameTag() + " selecting " + xPathImage + " from select='" + m_select + "' returned no model node"); } if (pathNodes.Count >= 1) { // there are some nodes - make a list m_names = null; foreach (XmlNode xname in pathNodes) { if (m_names == null) { if (m_path == null) { XmlPath xPath = new XmlPath(xname.ParentNode); m_path = xPath.Path; } } else { m_names += "/"; } string name = XmlFiler.getAttribute(xname, "name"); if (name == null || name == "") { m_names += "#NONE"; } else { m_names += name; } } } m_doneOnce = true; // avoid adding to m_path again on subsequent do-once iterations } if (m_selectPath != null && m_selectPath != "") { XmlPath node = SelectToPath(con, m_selectPath); // process m_select m_path = node.Path + m_path; } GuiPath gpath = new GuiPath(m_path); m_log.isNotNull(gpath, makeNameTag() + " attribute path='" + m_path + "' not parsed"); if (m_names != null) { m_list = Utilities.ParsePath(m_names); } PassFailInContext(m_onPass, m_onFail, out m_onPass, out m_onFail); AccessibilityHelper ah = con.Accessibility; m_log.isNotNull(ah, makeNameTag() + " context not accessible"); //check to see if it is visible m_Result = false; try { Application.Process.WaitForInputIdle(); } catch (Win32Exception e) { m_log.paragraph(makeNameTag() + " WaitForInputIdle: " + e.Message); m_Result = false; } if (m_Result) { ah = gpath.FindInGui(ah, null); } if (ah != null) { m_Result = GlimpseGUI(ah); } Finished = true; // tell do-once it's done if ((m_onPass == "assert" && m_Result == true) || (m_onFail == "assert" && m_Result == false)) { if (m_message != null) { m_log.fail(m_message.Read()); } else { m_log.fail(makeNameTag() + " Result = '" + m_Result + "', on-pass='******', on-fail='" + m_onFail + "'"); } } Logger.getOnly().result(this); }
// look for the expected dialog to appear. If it does, make an accessibilty // helper for it. public override void Execute() { // base.Execute(ts); // can't call this yet as it executes the children WaitMsec(); // do call this but make sure Wait is reset to zero! Wait = 0; // reset to zero so there is no delay after the dialog is found. // number is needed in diagnostics for the log if (Number == -1) { Number = TestState.getOnly().IncInstructionCount; } /// If present, use the selected dialog model title Context con = (Context)Ancestor(typeof(Context)); if (m_select != null && m_select != "") { // make a new model context node and move dialog's children to it m_select = Utilities.evalExpr(m_select); XmlDocument doc = m_elt.OwnerDocument; XmlElement modElt = doc.CreateElement("model"); modElt.SetAttribute("select", m_select); XmlNodeList children = m_elt.ChildNodes; int count = children.Count; while (count > 0) { // move dialog children to model XmlNode child = children.Item(0); //get the first child modElt.AppendChild(child); // automatically removed from m_elt!! count = children.Count; } m_elt.AppendChild(modElt); // set the title to look for // can only have one text node XmlNodeList pathNodes = Instructionator.selectNodes(this, m_select, makeName()); m_log.isNotNull(pathNodes, makeNameTag() + " select='" + m_select + "' returned no model"); m_log.isTrue(pathNodes.Count > 0, makeNameTag() + " select='" + m_select + "' returned no model nodes"); // This is the model node XmlNode modNode = pathNodes.Item(0); if (m_title == null || m_title == "") { // no title override, so set the title from the model string titleCheck = XmlFiler.getAttribute(modNode, "title"); if (titleCheck != null) { m_title = titleCheck; m_log.paragraph("on-dialog title set from selected model " + titleCheck); } } else { m_log.paragraph("on-dialog title set from @title " + m_title); } string nameCheck = XmlFiler.getAttribute(modNode, "name"); if (nameCheck != null) { m_name = nameCheck; m_log.paragraph("on-dialog name set from selected model " + nameCheck); } m_select = null; // can only do this one time in do-once or model } // if no name, try title if (m_title != null && m_title != "" && (m_name == null || m_name == "")) { m_name = m_title; } m_log.isNotNull(m_title, makeNameTag() + " No @title in script or model for this dialog."); m_log.isFalse(m_title == "", makeNameTag() + " @title in script or model is blank."); m_log.isFalse(m_name == null && !m_title.StartsWith("rexp#"), makeNameTag() + " No @name step in script or model for this dialog."); m_log.isFalse(m_name == "" && !m_title.StartsWith("rexp#"), makeNameTag() + " @name step in script or model is blank."); //if (m_title != null && m_title != "") m_title = Utilities.evalExpr(m_title); //if (m_name != null && m_name != "") m_name = Utilities.evalExpr(m_name); m_title = Utilities.evalExpr(m_title); m_name = Utilities.evalExpr(m_name); m_log.paragraph(image()); if (Application != null) { try { Application.Process.WaitForInputIdle(); } catch (Win32Exception e) { m_log.paragraph(makeNameTag() + " WaitForInputIdle: " + e.Message); } } // Give the window m_Rest seconds to show up int startTick = System.Environment.TickCount; IntPtr foundHwndPtr; string name = null; Regex rx = null; if (m_title != null && m_title.StartsWith("rexp#")) { // Create a regular expression object try { rx = new Regex(m_title.Substring(5)); } catch (ArgumentException e) { m_log.fail(makeNameTag() + " title from rexp# [" + m_title.Substring(5) + "] error: " + e.Message); } } while (!m_found) { // If there is a regular expression, try it. if (rx != null) { // try the main window name then other windows it may own via the regular expression m_log.paragraph("Searching all processes"); Process[] allProcs = Process.GetProcesses(); for (int p = 0; p < allProcs.Length; p++) { Process pro = allProcs[p]; try { if (rx.IsMatch(pro.MainWindowTitle)) { m_found = true; m_ah = new AccessibilityHelper(pro.Handle); break; } } catch (Exception e) { m_log.paragraph(makeNameTag() + " main title from rexp# [" + m_title.Substring(5) + "] process error: " + e.Message); } #region Attempt to explore process threads - useful? // try the windows that belong to this process /*try { * foreach (ProcessThread pt in pro.Threads) * { * * string para = "on-dialog matching proc [" + pro.ProcessName + ":"; * if (pt.Site != null) para += pt.Site.Name + "]"; * else para += "]"; * m_log.paragraph(para); * if (pt.Site != null && rx.IsMatch(pt.Site.Name)) { * m_found = true; * m_ah = new AccessibilityHelper(pro.Handle); * break; * } * } * } * catch (Exception e) * { * m_log.paragraph("on-dialog title from rexp# [" + m_title.Substring(5) + "] process error: " + e.Message); + } */ #endregion } } if (!m_found) { // get the window handle for windows with the right name // unfortuneately, other windows, or partially formed windows // seem to be obtained too. m_log.paragraph("Searching the desktop for a window via FindWindow"); if (rx != null) { foundHwndPtr = FindWindow(null, null); } else { foundHwndPtr = FindWindow(null, m_title); } if ((int)foundHwndPtr != 0) { // is this the window? Is it completely formed? m_ah = new AccessibilityHelper(foundHwndPtr); if (m_ah == null) { m_log.paragraph(makeNameTag() + " Obtained window with no Accessibiilty!"); } else // this window has accessibility - hope it's fully built { // is this or one of its children the window? name = m_ah.Name; //when name1 = "", m_ah is probably bad - i.e. not an object if (name == "") { } // do nothing, keep looking else if (name.Equals(m_title) || name.Equals(this.m_name)) { // this is likely it m_found = true; } else // m_ah might be the ah for the main app or dialog window { // Maybe one of its children is the window we want m_log.paragraph("Searching for a child window"); m_ah = m_ah.FindChild(m_title, AccessibleRole.Dialog); if (m_ah != null) { // is this the window? name = m_ah.Name; // name1 can't be null if (name == "") { } // do nothing, keep looking else if (name.Equals(m_title) || name.Equals(this.m_name)) { // this might be it m_found = true; } } } } } } if (Utilities.NumTicks(startTick, System.Environment.TickCount) > m_until) { break; // time is up } System.Threading.Thread.Sleep(100); } m_Rest = 0; // don't wait later when base.Execute is invoked if (m_found) { m_DlgHwndStack.Push(m_ah.HWnd); } else { // Didn't find the window m_ah = null; } string contextPass, contextFail; PassFailInContext(OnPass, OnFail, out contextPass, out contextFail); // out m_onPass, out m_onFail); m_log.paragraph(makeNameTag() + " passIn=" + OnPass + " failIn=" + OnFail + " pass="******" fail=" + contextFail); if (!m_found && contextFail == "skip") { return; // quietly exit } m_log.isTrue(m_found, makeNameTag() + m_title + @"' was not created or not accessible"); if (name == null) { m_log.paragraph(makeNameTag() + " Wierd: ah exists but name was null - should NEVER happen!!"); name = ""; } if (contextPass == "assert") { m_log.fail(makeNameTag() + m_title + " was not supposed to display."); } base.Execute(); m_log.result(this); base.Finished = true; // finished processing this dialog context m_DlgHwndStack.Pop(); if (m_DlgHwndStack.Count > 0) { int hwnd = (int)m_DlgHwndStack.Peek(); SendMessage((IntPtr)hwnd, (int)Msg.WM_SETFOCUS, 0, 0); m_log.paragraph(makeNameTag() + " Sent Focus message to containing context object"); // m_ah.Parent.SendWindowMessage((int)SIL.FieldWorks.Common.Utils.Win32.WinMsgs.WM_SETFOCUS,0,0); } }
/// <summary> /// Execute this model node context, specified by @select and /// creating and executing child instructions. /// </summary> public override void Execute() { base.Execute(); if (m_created) { Finished = true; // tell do-once it's done return; // all has been done in the base Context.Execute(). } Context con = (Context)Ancestor(typeof(Context)); isNotNull(con, makeNameTag() + " must occur in some context"); AccessibilityHelper ah = con.Accessibility; isNotNull(ah, makeNameTag() + " context is not accessible"); // If there is a @select, select the nodes if (m_select != null && m_select != "") { // each node or attribute selected creates a context m_log.paragraph(makeNameTag() + " creating selection targets via " + m_select); XmlNodeList pathNodes = XmlInstructionBuilder.selectNodes(con, m_select, makeNameTag()); isNotNull(pathNodes, makeNameTag() + " select='" + m_select + "' returned no model nodes"); // The select text may have selected a string that is itself xPath! // If so, select on that xPath if (pathNodes.Count == 1 && pathNodes.Item(0).NodeType == XmlNodeType.Text) { // this text node should be an xpath statement string xPath = pathNodes.Item(0).Value; m_log.paragraph(makeNameTag() + " selected a text node with more XPATH: " + xPath); pathNodes = XmlInstructionBuilder.selectNodes(con, xPath, makeNameTag() + " selecting " + xPath); isNotNull(pathNodes, makeNameTag() + " selecting " + xPath + " from select='" + m_select + "' returned no model nodes"); } // Create a list of paths to loop over Model lastModel = this; // use as an insert reference node foreach (XmlNode node in pathNodes) { // build the path via each model node XmlPath xPath = new XmlPath(node); // xPath may be invalid - it means it has no guiPath //if (!xPath.isValid()) fail(makeNameTag() + " XmlPath not constructable from " + node.OuterXml); if (1 == m_logLevel) { m_log.paragraph(makeNameTag() + " appPath " + xPath.xPath()); m_log.paragraph(makeNameTag() + " guiPath " + xPath.Path); } Model model = new Model(); model.m_created = true; model.m_modelNode = xPath; model.m_path = xPath.Path; model.m_select = xPath.xPath(); model.m_when = m_when; model.m_name = XmlFiler.getAttribute(node, "name"); model.m_role = XmlFiler.getAttribute(node, "role"); model.m_nodeName = node.Name; model.Number = TestState.getOnly().IncInstructionCount; model.Id += (model.Number - Number).ToString(); model.Parent = con; con.Add(lastModel, model); lastModel = model; // insert the next one after this one. m_log.mark(model); // log the progress of interpretation // if there is content, add instructions to the new model context if (m_elt.HasChildNodes) { foreach (XmlNode xnChild in m_elt.ChildNodes) { // a side-effect of MakeShell is to add the instruction to the model XmlInstructionBuilder.MakeShell(xnChild, model); } } } } Finished = true; // tell do-once it's done }
/// <summary> /// Read instruction file. /// Interpret script nodes according to tne instruction file. /// Make the class but don't process its child instructions if any. /// Don't execute the instruction. /// </summary> /// <param name="xn">The XML repersentation of the instruction to be checked</param> /// <param name="con">The current context object</param> /// <returns>Returns an unexecuted instruction or null</returns> static public Instruction MakeShell(XmlNode xn, Context con) { Logger.getOnly().isNotNull(xn, "Instruction can't be created from nothing!"); if (m_actPrototypes == null) { Logger.getOnly().fail("Can not create: No instruction prototypes loaded."); return null; } Instruction FluffedInstruction = null; // number the context if it doesn't have one yet to avoid depth-first numbering. if (con != null && con.Number == -1) con.Number = TestState.getOnly().IncInstructionCount; // figure out what to do with this node switch (xn.Name) { case "#comment": // ignore comments, etc.. case "#significant-whitespace": case "#whitespace": case "#text": break; default: // Find the instruction prototype based on node name. InsPrototype prototype = findPrototype(xn.Name, m_actPrototypes); if (prototype != null) { var AtValues = new ArrayList(); ArrayList atts = prototype.Attributes; Logger.getOnly().startList("Instruction " + prototype.Name); XmlAttributeCollection atNodes = xn.Attributes; if (atNodes != null && atts != null) { foreach (XmlAttribute atx in atNodes) { // find each attribute in the prototype string atValue = null; foreach (Attribute at in atts) { if (at.Name == atx.Name) { // its this one atValue = XmlFiler.getAttribute(xn, at.Name); if (atValue != null && at.Name != "log") { // log is dealt with in AddInstruction() var atVar = new Attribute(at.Name, atValue, at.Value); AtValues.Add(atVar); Logger.getOnly().listItem(" " + atx.Name + "=" + atValue); break; } } } if (atValue == null) { // This attribute is not expected: make it a variable // Add it as a var instruction so it gets bound at the right time // Use <var id="atx.Name" set="atValue"/> var var = new Var(); var.Id = atx.Name; var.Set = XmlFiler.getAttribute(xn, atx.Name); // Add the var to the growing list of instructions AddInstruction(xn, var, con); Logger.getOnly().paragraph("Added <var id=\"" + var.Id + "\" set=\"" + var.Set + "\"/>"); } } } Logger.getOnly().endList(); // Create the instruction using prototype.Name, AtValues.Name and AtValues.Value string protoName = XmlNameToCName(prototype.Name); string protoNameQ = prefix + protoName; Assembly assem = Assembly.GetExecutingAssembly(); // All instruction classes must have empty constructors Object protoInstruction = null; try { protoInstruction = assem.CreateInstance(protoNameQ, true, BindingFlags.CreateInstance, null, null, null, null);} catch (Exception e) { Logger.getOnly().fail("Instruction " + protoName + " not created: " + e.Message); } Logger.getOnly().isNotNull(protoInstruction, "Instruction " + protoName + " is DOA"); FluffedInstruction = (Instruction)protoInstruction; foreach (Attribute at in AtValues) { // Call each setter to set the instruction properties. int number = 0; UInt32 unsigned = 0; string primative = "string"; if (at.Type == "msec" || at.Type == "int" || at.Type.Contains("[0-10]")) { try { number = Convert.ToInt32(at.Value); primative = "int"; } catch (FormatException) { } } if (at.Type == "m-sec" || at.Type == "hz") { try { unsigned = Convert.ToUInt32(at.Value, 10); primative = "UInt32"; } catch (FormatException) { } } if (primative == "string" && at.Type.Contains("|")) { string[] enumList = makeEnumList(at.Type); foreach (string value in enumList) { if (value == at.Value) { primative = value; break; } } if (primative == "string") Logger.getOnly().fail("Invalid enum {" + at.Value + "} for " + protoNameQ + "." + at.Name + "(" + at.Type + ")"); } string propName = XmlNameToCName(at.Name); string propNameQ = protoNameQ + "." + XmlNameToCName(at.Name); PropertyInfo pi = null; MethodInfo m = null; try { if (primative == "int") { pi = assem.GetType(protoNameQ).GetProperty(propName, typeof(int)); m = pi.GetSetMethod(); m.Invoke(protoInstruction, new Object[] { number }); } else if (primative == "UInt32") { pi = assem.GetType(protoNameQ).GetProperty(propName, typeof(UInt32)); m = pi.GetSetMethod(); m.Invoke(protoInstruction, new Object[] { unsigned }); } else { Type t = assem.GetType(protoNameQ); pi = t.GetProperty(propName, typeof(string)); m = pi.GetSetMethod(); m.Invoke(protoInstruction, new Object[] { at.Value }); } } catch { Logger.getOnly().fail(" Can't find setter: " + protoNameQ + "." + propName + "(" + at.Type + ") using value {" + at.Value + "}"); } if (at.Name == "id" && protoName != "Var") TestState.getOnly().AddNamedInstruction(at.Value, FluffedInstruction); } // end of process attributes // Call the finishCreation method FluffedInstruction.finishCreation(xn, con); //if (prototype.Name != "if" && // prototype.Name != "then" && prototype.Name != "else") // Add the instruction to the growing list of instructions AddInstruction(xn, FluffedInstruction, con); } else { bool unknown = true; if (m_pasPrototypes != null) { InsPrototype IgnoredPrototype = findPrototype(xn.Name, m_pasPrototypes); if (IgnoredPrototype != null) unknown = false; } if (unknown) Logger.getOnly().fail("Can't make <" + xn.Name + "> instruction"); } break; } return FluffedInstruction; }