package cn.com.jautoitx; import java.awt.Frame; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; import java.util.List; import javax.swing.JFrame; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestName; import com.sun.jna.Native; import com.sun.jna.Platform; import com.sun.jna.Structure; import com.sun.jna.WString; import com.sun.jna.platform.win32.Netapi32; import com.sun.jna.platform.win32.User32; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.W32APIOptions; public abstract class BaseTest { protected static final boolean isZhUserLanguage = "zh" .equalsIgnoreCase(System.getProperty("user.language")) || "Cp1252" .equalsIgnoreCase(System.getProperty("sun.jnu.encoding")); protected static final String SAVE_AS_DIALOG_TITLE = isZhUserLanguage ? "另存为" : "Save As"; /* Notepad */ protected static final String NOTEPAD_PROC_NAME = "notepad.exe"; protected static final String NOTEPAAD_CLASS_NAME = "Notepad"; protected static final String NOTEPAAD_CLASS_LIST = "Edit\nmsctls_statusbar32\n"; protected static final String NOTEPAD_TITLE = isZhUserLanguage ? "无标题 - 记事本" : "Untitled - Notepad"; protected static final String NOTEPAD_TITLE_START = isZhUserLanguage ? "无标题" : "Untitled"; protected static final String NOTEPAD_TITLE_ANY = isZhUserLanguage ? "题 - 记" : "titled - Note"; protected static final String NOTEPAD_TITLE_END = isZhUserLanguage ? "记事本" : "Notepad"; /* HashMyFiles */ protected static final String HASH_MY_FILES_PROC_NAME = "HashMyFiles" + (Platform.is64Bit() ? "_x64" : "") + ".exe"; protected static final String HASH_MY_FILES = new File("test/" + HASH_MY_FILES_PROC_NAME).getAbsolutePath(); protected static final String HASH_MY_FILES_TITLE = "HashMyFiles"; protected static final String HASH_MY_FILES_ADD_FILES_TITLE = "Select one or more filenames to add"; /* Windows task manager */ protected static final String TASK_MANAGER = "taskmgr.exe"; protected static final String TASK_MANAGER_TITLE = isZhUserLanguage ? "Windows 任务管理器" : "Windows Task Manager"; protected static final String STATUS_BAR_TEXT_PROCESSES = isZhUserLanguage ? "进程数:" : "Processes:"; protected static final String STATUS_BAR_TEXT_CPU_USAGE = isZhUserLanguage ? "CPU 使用" : "CPU Usage:"; protected static final String STATUS_BAR_TEXT_COMMIT_CHARGE = isZhUserLanguage ? "提交更改:" : "Commit Charge:"; protected static final String STATUS_BAR_TEXT_PHYSICAL_MEMORY = isZhUserLanguage ? "物理内存:" : "Physical Memory:"; protected static final String STATUS_BAR_TEXT_MEMORY_USAGE = isZhUserLanguage ? "内存使用:" : "Memory Usage:"; protected static final String MESSAGE_BOX_OK_BUTTON_TEXT = isZhUserLanguage ? "确定" : "OK"; protected static final int NET_SHARE_PERMISSION_ACCESS_NONE = 0; protected static final int NET_SHARE_PERMISSION_ACCESS_READ = 1; @Rule public TestName testName = new TestName(); /* System current time before run every test */ protected long currentTimeMillis = 0; @Before public void setUp() { System.out.println(String.format( "--------------------Begin test %s#%s", getClass().getName(), testName.getMethodName())); Integer pid = 0; // close notepad while ((pid = Process.exists(NOTEPAD_PROC_NAME)) != null) { Process.close(pid); } // close HashMyFiles while ((pid = Process.exists(HASH_MY_FILES_PROC_NAME)) != null) { Process.close(pid); } // close windows task manager while ((pid = Process.exists(TASK_MANAGER)) != null) { Process.close(pid); } sleep(200); currentTimeMillis = System.currentTimeMillis(); } @After public void tearDown() { System.out.println(String.format( "--------------------End test %s#%s%n", getClass().getName(), testName.getMethodName())); } protected void assertEquals(int expected, Integer actual) { Assert.assertNotNull(actual); Assert.assertEquals(expected, (int) actual); } protected void assertEquals(String expected, String actual) { Assert.assertEquals(expected, actual); } protected void assertEmpty(final String text) { Assert.assertTrue(StringUtils.isEmpty(text)); } protected void assertBlank(final String text) { Assert.assertTrue(StringUtils.isBlank(text)); } protected void assertNotEmpty(final String text) { Assert.assertTrue(StringUtils.isNotEmpty(text)); } protected void assertNotBlank(final String text) { Assert.assertTrue(StringUtils.isNotBlank(text)); } protected void assertFileContent(final String filePath, final String content) { assertNotBlank(filePath); try { Assert.assertEquals(content, FileUtils.readFileToString(new File(filePath))); } catch (IOException e) { e.printStackTrace(); Assert.fail("Get content from file " + filePath + " failed."); } } protected void destroyFrame(Frame frame) { if (frame != null) { frame.setVisible(false); frame.dispose(); } } protected void destroyFrame(JFrame frame) { if (frame != null) { frame.setVisible(false); frame.dispose(); } } protected void destroyDefaultDisplay(String title) { final Display display = Display.getDefault(); if (display != null) { display.syncExec(new Runnable() { public void run() { Shell[] shells = display.getShells(); if (shells != null) { for (Shell shell : shells) { shell.setVisible(false); shell.close(); shell.dispose(); } } display.dispose(); } }); Assert.assertTrue(Win.waitClose(title)); } } protected int runNotepad() { // run notepad Integer pid = Process.run(NOTEPAD_PROC_NAME); Assert.assertNotNull(pid); Assert.assertTrue(Win.waitActive(NOTEPAD_TITLE, 3)); return pid; } protected void closeNotepad(int pid) { if (pid > 0) { // close notepad Process.close(pid); sleep(500); Assert.assertFalse(Process.exists(pid)); } } protected void sleep(final long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); Assert.fail(String.format("Thread.sleep(%d) failed.", millis)); } } protected String getTooltip(final String handle) { Assert.assertTrue(StringUtils.isNotBlank(handle)); HWND hWnd = AutoItX.handleToHwnd(handle); // check className char[] lpClassName = new char[50]; int classNameLength = User32.INSTANCE.GetClassName(hWnd, lpClassName, lpClassName.length); String className = (classNameLength > 0) ? new String(lpClassName, 0, classNameLength) : ""; if (!"tooltips_class32".equals(className)) { return ""; } char[] tooltip = new char[User32.INSTANCE.GetWindowTextLength(hWnd) + 1]; int length = User32.INSTANCE.GetWindowText(hWnd, tooltip, tooltip.length); return new String(tooltip, 0, length); } protected String getHostAddress() { try { return InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { Assert.fail("getHostAddress failed: " + e.getMessage()); return null; } } /** * Shares a server resource. * * @param servername * @param netname * @param remark * @param permissions * @param path * @param passwd * @return */ protected boolean netShareAdd(String servername, String netname, String remark, int permissions, String path, String passwd) { SHARE_INFO_2 buf = new SHARE_INFO_2(); buf.shi2_netname = (netname == null) ? null : new WString(netname); // STYPE_DISKTREE buf.shi2_type = 0; buf.shi2_remark = (remark == null) ? null : new WString(remark); buf.shi2_permissions = permissions; buf.shi2_max_uses = 1; buf.shi2_current_uses = 0; buf.shi2_path = (path == null) ? null : new WString(path); buf.shi2_passwd = (passwd == null) ? null : new WString(passwd); IntByReference parm_err = new IntByReference(); // If the function succeeds, the return value is NERR_Success int res = Netapi32Ext.INSTANCE .NetShareAdd(servername, 2, buf, parm_err); if (res == 0) { return true; } System.err.println("netname = " + netname + ", remark = " + remark + ", path = " + path + ", passwd = " + passwd + ", res = " + res + ", parm_err = " + parm_err.getValue()); return false; } /** * Deletes a share name from a server's list of shared resources, * disconnecting all connections to the shared resource. * * @param servername * @param netname * @return */ protected boolean netShareDel(String servername, String netname) { // If the function succeeds, the return value is NERR_Success int res = Netapi32Ext.INSTANCE.NetShareDel(servername, netname, 0); if (res == 0) { return true; } System.err.println("res = " + res); return false; } protected static interface Netapi32Ext extends Netapi32 { Netapi32Ext INSTANCE = (Netapi32Ext) Native.loadLibrary("Netapi32", Netapi32Ext.class, W32APIOptions.DEFAULT_OPTIONS); /** * Shares a server resource. * * @param servername * Pointer to a string that specifies the DNS or NetBIOS name * of the remote server on which the function is to execute. * If this parameter is NULL, the local computer is used. * @param level * Specifies the information level of the data. This * parameter can be one of the following values.<br/> * 2:<br/> * Specifies information about the shared resource, including * the name of the resource, type and permissions, and number * of connections. The buf parameter points to a SHARE_INFO_2 * structure. * * 502:<br/> * Specifies information about the shared resource, including * the name of the resource, type and permissions, number of * connections, and other pertinent information. The buf * parameter points to a SHARE_INFO_502 structure. * * 503:<br/> * Specifies information about the shared resource, including * the name of the resource, type and permissions, number of * connections, and other pertinent information. The buf * parameter points to a SHARE_INFO_503 structure. * @param buf * Pointer to the buffer that specifies the data. The format * of this data depends on the value of the level parameter. * For more information, see <a href= * "http://msdn.microsoft.com/en-us/library/aa370676(v=vs.85).aspx" * >Network Management Function Buffers</a>. * @param parm_err * Pointer to a value that receives the index of the first * member of the share information structure that causes the * ERROR_INVALID_PARAMETER error. If this parameter is NULL, * the index is not returned on error. For more information, * see the NetShareSetInfo function. * @return If the function succeeds, the return value is NERR_Success. * If the function fails, the return value can be one of the * following error codes. */ int NetShareAdd(String servername, int level, SHARE_INFO_2 buf, IntByReference parm_err); /** * Deletes a share name from a server's list of shared resources, * disconnecting all connections to the shared resource. * * @param servername * Pointer to a string that specifies the DNS or NetBIOS name * of the remote server on which the function is to execute. * If this parameter is NULL, the local computer is used. * @param netname * Pointer to a string that specifies the name of the share * to delete. This string is Unicode if _WIN32_WINNT or * FORCE_UNICODE is defined. * @param reversed * Reserved, must be zero. * @return If the function succeeds, the return value is NERR_Success. * If the function fails, the return value can be one of the * following error codes. */ int NetShareDel(String servername, String netname, int reversed); } /** * Contains information about the shared resource, including name of the * resource, type and permissions, and the number of current connections. * For more information about controlling access to securable objects, see * Access Control, Privileges, and Securable Objects. * * @author zhengbo.wang */ protected static class SHARE_INFO_2 extends Structure { /* * Pointer to a Unicode string specifying the share name of a resource. * Calls to the NetShareSetInfo function ignore this member. */ public WString shi2_netname; /* * A combination of values that specify the type of the shared resource. * Calls to the NetShareSetInfo function ignore this member. One of the * following values may be specified. You can isolate these values by * using the STYPE_MASK value. */ public int shi2_type; /* * Pointer to a Unicode string that contains an optional comment about * the shared resource. */ public WString shi2_remark; /* * Specifies a DWORD value that indicates the shared resource's * permissions for servers running with share-level security. A server * running user-level security ignores this member. This member can be * one or more of the following values. Calls to the NetShareSetInfo * function ignore this member. Note that Windows does not support * share-level security. */ public int shi2_permissions; /* * Specifies a DWORD value that indicates the maximum number of * concurrent connections that the shared resource can accommodate. The * number of connections is unlimited if the value specified in this * member is -1. */ public int shi2_max_uses; /* * Specifies a DWORD value that indicates the number of current * connections to the resource. Calls to the NetShareSetInfo function * ignore this member. */ public int shi2_current_uses; /* * Pointer to a Unicode string specifying the local path for the shared * resource. For disks, shi2_path is the path being shared. For print * queues, shi2_path is the name of the print queue being shared. Calls * to the NetShareSetInfo function ignore this member. */ public WString shi2_path; /* * Pointer to a Unicode string that specifies the share's password when * the server is running with share-level security. If the server is * running with user-level security, this member is ignored. The * shi2_passwd member can be no longer than SHPWLEN+1 bytes (including a * terminating null character). Calls to the NetShareSetInfo function * ignore this member. Note that Windows does not support share-level * security. */ public WString shi2_passwd; @SuppressWarnings("rawtypes") @Override protected List getFieldOrder() { return Arrays.asList("shi2_netname", "shi2_type", "shi2_remark", "shi2_permissions", "shi2_max_uses", "shi2_current_uses", "shi2_path", "shi2_passwd"); } } protected static class ObjectHolder { public Object value = null; public ObjectHolder() { // empty } public ObjectHolder(Object value) { this.value = value; } } }