/// <summary> /// Launch the application to test. /// </summary> /// <returns>true if the application launched successfully.</returns> private bool LaunchApp(string exePath, string exeName, string args, string workDir) { // Launch the Application bool fStarted = true; if (!Utilities.isGoodStr(exePath)) { m_log.writeEltTime("fail"); m_log.writeAttr("exe-path", "null or empty"); m_log.endElt(); return false; } if (!Utilities.isGoodStr(exeName)) { m_log.writeEltTime("fail"); m_log.writeAttr("exe-name", "null or empty"); m_log.endElt(); return false; } string fullPath = exePath + @"\" + exeName + @".exe"; // Need to set the working directory to m_path Process proc = new Process(); if (!Utilities.isGoodStr(exeName)) { // can proc ever be null? m_log.writeEltTime("fail"); m_log.writeAttr("splash-screen", "could not create"); m_log.writeAttr("exe-full-path", fullPath); m_log.endElt(); return false; } proc.StartInfo.FileName = fullPath; if (args != null) proc.StartInfo.Arguments = args; //proc.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs"; proc.StartInfo.UseShellExecute = false; //compiler.StartInfo.RedirectStandardOutput = true; if (workDir != null) proc.StartInfo.WorkingDirectory = workDir; else proc.StartInfo.WorkingDirectory = exePath; proc.Start(); if (proc == null) { // can this happen? m_log.writeEltTime("fail"); m_log.writeAttr("splash-screen", "null process"); m_log.writeAttr("exe-full-path", fullPath); m_log.endElt(); return false; } proc.WaitForInputIdle(); m_log.writeEltTime("splash-exited"); m_log.endElt(); proc.Refresh(); // sometimes the proc gets stale. // proc.MainWindowHandle is always IntPtr.Zero // so, get another process that has proc.Id // Process pOfId = Process.GetProcessById(proc.Id); Process pOfId = proc; if (pOfId == null) { m_log.writeEltTime("fail"); m_log.writeAttr("main-window", "null process"); m_log.writeAttr("exe-full-path", fullPath); m_log.endElt(); return false; } pOfId.WaitForInputIdle(); IntPtr hWnd; try { hWnd = pOfId.MainWindowHandle; } catch (InvalidOperationException e) { m_log.writeEltTime("fail"); m_log.writeAttr("main-window", "handle not grasped"); m_log.writeAttr("exe-full-path", fullPath); m_log.writeAttr("message", e.Message); m_log.endElt(); return false; } // tried Form.FromHandle(hWnd), Form.FromChildHandle(hWnd), NativeWindow.FromHandle(hWnd); // They return null because the hWnd comes from another process. // make the window show itself if (pOfId.MainWindowTitle == null) { m_log.writeEltTime("fail"); m_log.writeAttr("main-window", "no title"); m_log.writeAttr("exe-full-path", fullPath); m_log.endElt(); return false; } SetForegroundWindow(pOfId.MainWindowHandle); // get a new accessibility object as it has more nodes in it now. m_ah = new AccessibilityHelper(pOfId.MainWindowHandle); if (m_ah == null) { m_log.writeEltTime("fail"); m_log.writeAttr("main-window", "not accessible"); m_log.writeAttr("title", pOfId.MainWindowTitle); m_log.endElt(); return false; } m_proc = proc; return fStarted; }
/// <summary> /// Examines the GUI for the value of the property specified via @prop. /// If @expect is set, the @prop value is compared to it. /// The result is true when @expect = the @prop GUI value. /// When @prop names a boolean property, and @expect is not set, then /// the boolean value is the result. /// </summary> /// <param name="ah">Context accessibility helper, taken as the starting place for gpath.</param> /// <param name="property">The property value to look at.</param> /// <param name="expect">The expected value of the prop attribute.</param> /// <returns>True if @expect = @prop GUI value, false otherwise, or the boolean value of @prop in the GUI.</returns> bool GlimpseGUI(AccessibilityHelper ah, string property, string expect) { bool result = true; string got = null; if (ah == null) { if (property == "absent") return true; return false; } if (property == null) property = "present"; switch (property) { case "children": { if (expect == null) expect = "0"; if (Utilities.IsNumber(expect) == false) return false; // fail("children requires an integer not '" + expect + "'."); int val = ah.ChildCount; got = val.ToString(); result = val.Equals((int)Utilities.GetNumber(expect)); break; } case "handle": { if (expect == null) expect = "0"; if (Utilities.IsNumber(expect) == false) return false; // fail("handle requires a big integer not '" + expect + "'."); int val = ah.HWnd; got = val.ToString(); result = val.Equals((int)Utilities.GetNumber(expect)); break; } case "hotkey": { got = ah.Shortcut; if (got == null || got == "") got = "NONE"; result = got == expect; // neither can be null break; } case "name": { got = ah.Name; if (got == null) got = "NAMELESS"; result = got == expect; // neither can be null break; } case "role": { if (expect == null) expect = "none"; got = ah.Role.ToString(); result = got == expect; break; } case "value": { got = ah.Value; if (expect != null && expect.StartsWith("rexp#")) { Regex rx = new Regex(expect.Substring(5)); result = rx.IsMatch(got); m_log.writeElt("regular-expression"); m_log.writeAttr("expect", expect.Substring(5)); m_log.writeAttr("on", got); m_log.writeAttr("was", result.ToString()); m_log.endElt(); } else result = got == expect; // either can be null break; } case "visible": { if (expect == null) expect = "True"; result = !(((AccessibleStates.Invisible & ah.States) == AccessibleStates.Invisible) || ((AccessibleStates.Offscreen & ah.States) == AccessibleStates.Offscreen)); got = result.ToString(); result = got.ToLower() == expect.ToLower(); break; } case "checked": { if (expect == null) expect = "True"; result = ((AccessibleStates.Checked & ah.States) == AccessibleStates.Checked); got = result.ToString(); result = got.ToLower() == expect.ToLower(); break; } case "selected": { if (expect == null) expect = "True"; result = ((AccessibleStates.Selected & ah.States) == AccessibleStates.Selected); got = result.ToString(); result = got.ToLower() == expect.ToLower(); break; } case "present": break; case "unavailable": { if (expect == null) expect = "True"; result = ((AccessibleStates.Unavailable & ah.States) == AccessibleStates.Unavailable); got = result.ToString(); result = got.ToLower() == expect.ToLower(); break; } default: { m_log.writeElt("glimpse-fail"); m_log.writeAttr("prop", property); m_log.writeAttr("was", "not understood"); m_log.endElt(); got = result.ToString(); result = false; break; } } return result; }
/// <summary> /// method to apply when a non-terminal node has been found /// </summary> /// <param name="ah"></param> public void visitNode(AccessibilityHelper ah) { // does this ah need to be clicked or something to get to its children? if (ah.Role == AccessibleRole.MenuItem) { bool isFocused = (ah.States & AccessibleStates.Focused) == AccessibleStates.Focused; if (!isFocused) ah.SimulateClickRelative(10, 10); else ah.MoveMouseOverMe(); // hover } }
/// <summary> /// Determines the result of a Simian sensation. /// Problems with sensors are not generally logged /// since they are frequently called and most are not /// fatal. /// </summary> /// <param name="sensorRef">A sensor expression in a rule.</param> /// <returns>true if the sensor detected its target.</returns> public bool sensation(EmptyElement sensorRef) { if (sensorRef.getName().Equals("window")) { // is the window showing? string id = sensorRef.getValue("id"); // a VarNode string title = sensorRef.getValue("title"); MarkedNode mn = null; if (Utilities.isGoodStr(id) && Utilities.isGoodStr(title)) { // fetch the title from the model node via id + title mn = m_varNodes.get(id); // bail out if id not defined yet. if (mn == null) return false; if (mn.node != null) title = m_GuiModel.selectToString(mn.node, title, "title"); if (!Utilities.isGoodStr(title)) return false; } else if (id == null && title == null) { // get the main window title from the model title = m_Config.getDataBase()+m_GuiModel.getTitle(); } if (title == null) return false; // model lacks title if (Utilities.isGoodStr(title)) { IntPtr winHand = FindWindow(null, title); if ((int)winHand != 0) { AccessibilityHelper ah = new AccessibilityHelper(winHand); // look for a titlebar GuiPath gPath = new GuiPath("1:NAMELESS"); AccessibilityHelper tah = ah.SearchPath(gPath, this); if (tah == null || !tah.Value.Equals(title)) return false; m_ah = ah; return true; } } } if (sensorRef.getName().Equals("tested")) { string id = sensorRef.getValue("id"); // which controls string control = sensorRef.getValue("control"); // which controls string count = sensorRef.getValue("count"); // indicates how many if (control != null && count == null) return false; if (control == null && count != null) return false; if (control == null && count == null && id == null) return false; if (id != null) { MarkedNode mn = m_varNodes.get(id); if (mn != null) { if (mn.mark == null) return false; return mn.mark.Equals("tested"); } } // if id fails to return a marked node, try a control count if (control != null) { int n = 0; int k = 0; if (control.Equals("view")) { if (m_views == null) m_views = new MarkedList(m_GuiModel, "//*[@role='view']"); n = m_views.Count(); k = m_views.Count("tested"); } if (count.Equals("all") && n == k) return true; if (count.Equals("not-all") && k < n) return true; return false; } return false; } if (sensorRef.getName().Equals("glimpse")) { string id = sensorRef.getValue("id"); // a VarNode string appPath = sensorRef.getValue("on"); // an appPath string guiPath = sensorRef.getValue("at"); // a giuPath string property = sensorRef.getValue("prop"); // an ah property string expect = sensorRef.getValue("expect"); // value expected // Id provides a context ah that must be used to find the rest of the path! // can't just use the appPath from it. What if it's a dialog? XmlNode context = null; MarkedNode mn = null; if (Utilities.isGoodStr(id)) { mn = m_varNodes.get(id); // bail out if id not defined yet. if (mn == null) return false; if (mn.node != null) context = mn.node; } return glimpse(context, appPath, guiPath, property, expect); } return false; }
/// <summary> /// Collects ah's associated with steps in a path. /// </summary> /// <param name="ah">The ah of a non-terminal node found along a path</param> public void visitNode(AccessibilityHelper ah) { // add them so the first to be visited later is the first one added. base.Add(ah); }
/// <summary> /// Find the GUI element represented by this path step in the application GUI /// beginning from the context specified. /// /// </summary> /// <param name="ahContext">The context to start the search from</param> /// <param name="visitor">The class with the visitNode() method to /// apply to each node except the last found, may be null</param> /// <returns>The AccessibilityHelper of the last node found or null if the path does not exist</returns> public AccessibilityHelper FindInGui(AccessibilityHelper ahContext, IPathVisitor visitor) { if (ahContext == null) return null; AccessibilityHelper ah = ahContext; if (m_name == "#focus") { // get the ah from the focused Gui element ah = ah.GetFocused; } else ah = ah.SearchPath(this, visitor); return ah; }