]> git.saurik.com Git - wxWidgets.git/commitdiff
Run wxExecute() unit test in the GUI test suite too.
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 3 Jul 2013 00:32:40 +0000 (00:32 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 3 Jul 2013 00:32:40 +0000 (00:32 +0000)
The same code works differently in console and GUI applications, so build this
test case as part of both of them.

See #10258.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74351 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

12 files changed:
tests/Makefile.in
tests/exec/exec.cpp
tests/makefile.bcc
tests/makefile.gcc
tests/makefile.vc
tests/makefile.wat
tests/test.bkl
tests/test_test.dsp
tests/test_test_gui.dsp
tests/test_vc7_test_gui.vcproj
tests/test_vc8_test_gui.vcproj
tests/test_vc9_test_gui.vcproj

index 14da03c03cbc2628fb3fb5df43d66d42cb68f014..cb8c20701274bd61f30eabd9311ee544f7bae989 100644 (file)
@@ -212,6 +212,7 @@ TEST_GUI_OBJECTS =  \
        test_gui_evtlooptest.o \
        test_gui_propagation.o \
        test_gui_keyboard.o \
+       test_gui_exec.o \
        test_gui_fonttest.o \
        test_gui_image.o \
        test_gui_rawbmp.o \
@@ -895,6 +896,9 @@ test_gui_propagation.o: $(srcdir)/events/propagation.cpp $(TEST_GUI_ODEP)
 test_gui_keyboard.o: $(srcdir)/events/keyboard.cpp $(TEST_GUI_ODEP)
        $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/events/keyboard.cpp
 
+test_gui_exec.o: $(srcdir)/exec/exec.cpp $(TEST_GUI_ODEP)
+       $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/exec/exec.cpp
+
 test_gui_fonttest.o: $(srcdir)/font/fonttest.cpp $(TEST_GUI_ODEP)
        $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/font/fonttest.cpp
 
index d9e61fdfff7a1dc8148a7cfc302a4c2fb9763347..7a4ee95b6fae80bb0beebed027b8ae1eafa9221e 100644 (file)
 #include "wx/utils.h"
 #include "wx/process.h"
 #include "wx/sstream.h"
+#include "wx/evtloop.h"
+#include "wx/file.h"
+#include "wx/filename.h"
+#include "wx/mstream.h"
+#include "wx/scopeguard.h"
+#include "wx/txtstrm.h"
+#include "wx/timer.h"
 
 #ifdef __UNIX__
     #define COMMAND "echo hi"
+    #define COMMAND_STDERR "cat nonexistentfile"
     #define ASYNC_COMMAND "xclock"
     #define SHELL_COMMAND "echo hi from shell>/dev/null"
     #define COMMAND_NO_OUTPUT "echo -n"
 #elif defined(__WINDOWS__)
     #define COMMAND "cmd.exe /c \"echo hi\""
+    #define COMMAND_STDERR "cmd.exe /c \"type nonexistentfile\""
     #define ASYNC_COMMAND "notepad"
     #define SHELL_COMMAND "echo hi > nul:"
     #define COMMAND_NO_OUTPUT COMMAND " > nul:"
@@ -38,6 +47,8 @@
     #error "no command to exec"
 #endif // OS
 
+#define SLEEP_END_STRING "Done sleeping"
+
 // ----------------------------------------------------------------------------
 // test class
 // ----------------------------------------------------------------------------
@@ -52,11 +63,90 @@ private:
         CPPUNIT_TEST( TestShell );
         CPPUNIT_TEST( TestExecute );
         CPPUNIT_TEST( TestProcess );
+        CPPUNIT_TEST( TestAsync );
+        CPPUNIT_TEST( TestAsyncRedirect );
+        CPPUNIT_TEST( TestOverlappedSyncExecute );
     CPPUNIT_TEST_SUITE_END();
 
     void TestShell();
     void TestExecute();
     void TestProcess();
+    void TestAsync();
+    void TestAsyncRedirect();
+    void TestOverlappedSyncExecute();
+
+    // Helper: create an executable file sleeping for the given amount of
+    // seconds with the specified base name.
+    //
+    // Returns the name of the file.
+    static wxString CreateSleepFile(const wxString& basename, int seconds);
+
+    // Return the full command, to be passed to wxExecute(), launching the
+    // specified script file.
+    static wxString MakeShellCommand(const wxString& filename);
+
+
+    // Helper of TestAsyncRedirect(): tests that the output of the given
+    // command on the given stream contains the expected string.
+    enum CheckStream { Check_Stdout, Check_Stderr };
+
+    void DoTestAsyncRedirect(const wxString& command,
+                             CheckStream check,
+                             const char* expectedContaining);
+
+    enum AsyncExecLoopExitEnum
+    {
+        AsyncExec_DontExitLoop,
+        AsyncExec_ExitLoop
+    };
+
+    // This class is used as a helper in order to run wxExecute(ASYNC)
+    // inside of an event loop.
+    class AsyncInEventLoop : public wxTimer
+    {
+    public:
+        AsyncInEventLoop() { }
+
+        long DoExecute(AsyncExecLoopExitEnum forceExitLoop_,
+                     const wxString& command_,
+                     int flags_ = wxEXEC_ASYNC,
+                     wxProcess* callback_ = NULL)
+        {
+            forceExitLoop = forceExitLoop_;
+            command = command_;
+            flags = flags_;
+            callback = callback_;
+
+            wxEventLoop loop;
+
+            // Trigger the timer to go off inside the event loop
+            // so that we can run wxExecute there.
+            StartOnce(10);
+
+            // Run the event loop.
+            loop.Run();
+
+            return wxExecuteReturnCode;
+        }
+
+        void Notify()
+        {
+            // Run wxExecute inside the event loop.
+            wxExecuteReturnCode = wxExecute(command, flags, callback);
+
+            if (forceExitLoop == AsyncExec_ExitLoop)
+            {
+                wxEventLoop::GetActive()->Exit();
+            }
+        }
+
+    private:
+        AsyncExecLoopExitEnum forceExitLoop;
+        wxString command;
+        int flags;
+        wxProcess* callback;
+        long wxExecuteReturnCode;
+    };
 
     DECLARE_NO_COPY_CLASS(ExecTestCase)
 };
@@ -75,12 +165,18 @@ void ExecTestCase::TestShell()
 
 void ExecTestCase::TestExecute()
 {
-    // test sync exec (with a command not producing any output to avoid
-    // interfering with the test):
-    CPPUNIT_ASSERT( wxExecute(COMMAND_NO_OUTPUT, wxEXEC_SYNC) == 0 );
+    AsyncInEventLoop asyncInEventLoop;
 
     // test asynch exec
-    long pid = wxExecute(ASYNC_COMMAND, wxEXEC_ASYNC);
+    //
+    // asyncInEventLoop.DoExecute will perform the
+    // call to wxExecute(ASYNC) in an event loop, as required by
+    // console test (and this same event loop will also
+    // be used in GUI test too, even though not required, just to have
+    // common code).
+    long pid = asyncInEventLoop.DoExecute(AsyncExec_ExitLoop, // Force exit of event loop right
+                                                // after the call to wxExecute()
+                                          ASYNC_COMMAND, wxEXEC_ASYNC);
     CPPUNIT_ASSERT( pid != 0 );
 
     // NOTE: under Windows the first wxKill() invocation with wxSIGTERM
@@ -91,17 +187,62 @@ void ExecTestCase::TestExecute()
     CPPUNIT_ASSERT( wxKill(pid, wxSIGTERM) == 0 ||
                     wxKill(pid, wxSIGKILL) == 0 );
 
-    // test running COMMAND again, but this time with redirection:
-    wxArrayString stdout_arr;
-    CPPUNIT_ASSERT_EQUAL( 0, wxExecute(COMMAND, stdout_arr, wxEXEC_SYNC) );
-    CPPUNIT_ASSERT_EQUAL( "hi", stdout_arr[0] );
+    int useNoeventsFlag;
+
+    // Test the sync execution case with/without wxEXEC_NOEVENTS flag
+    // because we use either an event loop or wxSelectDispatcher
+    // depending on this flag, and we want to test both cases.
+    for (useNoeventsFlag = 0; useNoeventsFlag <=1 ; ++useNoeventsFlag )
+    {
+        int execFlags = wxEXEC_SYNC;
+
+        if (useNoeventsFlag)
+        {
+            execFlags |= wxEXEC_NOEVENTS;
+        }
+
+        // test sync exec (with a command not producing any output to avoid
+        // interfering with the test):
+        CPPUNIT_ASSERT( wxExecute(COMMAND_NO_OUTPUT, execFlags) == 0 );
+
+        // test running COMMAND again, but this time with redirection:
+        // and the expected data is on stdout.
+        wxArrayString stdout_arr;
+        CPPUNIT_ASSERT_EQUAL( 0, wxExecute(COMMAND, stdout_arr, execFlags) );
+        CPPUNIT_ASSERT_EQUAL( "hi", stdout_arr[0] );
+
+        // test running COMMAND_STDERR with redirection and the expected data
+        // is on stderr.
+        wxArrayString stderr_arr;
+        stdout_arr.Empty();
+        CPPUNIT_ASSERT( wxExecute(COMMAND_STDERR, stdout_arr, stderr_arr, execFlags) != 0 );
+
+        // Check that there is something on stderr.
+        // In Unix systems, the 'cat' command has the name of the file it could not
+        // find in the error output.
+        // In Windows, the 'type' command outputs the following when it can't find
+        // a file:
+        // "The system cannot find the file specified"
+        // In both cases, we expect the word 'file' to be in the stderr.
+        CPPUNIT_ASSERT( stderr_arr[0].Contains("file") );
+    }
 }
 
 void ExecTestCase::TestProcess()
 {
+    AsyncInEventLoop asyncInEventLoop;
+
     // test wxExecute with wxProcess
     wxProcess *proc = new wxProcess;
-    long pid = wxExecute(ASYNC_COMMAND, wxEXEC_ASYNC, proc);
+
+    // asyncInEventLoop.DoExecute will perform the
+    // call to wxExecute(ASYNC) in an event loop, as required by
+    // console test (and this same event loop will also
+    // be used in GUI test too, even though not required, just to have
+    // common code).
+    long pid = asyncInEventLoop.DoExecute(AsyncExec_ExitLoop, // Force exit of event loop right
+                                                // after the call to wxExecute()
+                                          ASYNC_COMMAND, wxEXEC_ASYNC, proc);
     CPPUNIT_ASSERT( proc->GetPid() == pid && pid != 0 );
 
     // we're not going to process the wxEVT_END_PROCESS event,
@@ -112,16 +253,244 @@ void ExecTestCase::TestProcess()
 
 
     // test wxExecute with wxProcess and REDIRECTION
-    wxProcess *proc2 = new wxProcess;
-    proc2->Redirect();
-    CPPUNIT_ASSERT( wxExecute(COMMAND, wxEXEC_SYNC, proc2) == 0 );
 
-    wxStringOutputStream stdout_stream;
-    CPPUNIT_ASSERT( proc2->GetInputStream() );
-    CPPUNIT_ASSERT_EQUAL( wxSTREAM_EOF,
-        proc2->GetInputStream()->Read(stdout_stream).GetLastError() );
+    // Test the sync execution case with/without wxEXEC_NOEVENTS flag
+    // because we use either an event loop or wxSelectDispatcher
+    // depending on this flag, and we want to test both cases.
+
+    // First the default case, dispatching the events while waiting.
+    {
+        wxProcess proc2;
+        proc2.Redirect();
+        CPPUNIT_ASSERT_EQUAL( 0, wxExecute(COMMAND, wxEXEC_SYNC, &proc2) );
+
+        wxStringOutputStream procOutput;
+        CPPUNIT_ASSERT( proc2.GetInputStream() );
+        CPPUNIT_ASSERT_EQUAL( wxSTREAM_EOF,
+            proc2.GetInputStream()->Read(procOutput).GetLastError() );
+
+        wxString output = procOutput.GetString();
+        CPPUNIT_ASSERT_EQUAL( "hi", output.Trim() );
+    }
+
+    // And now without event dispatching.
+    {
+        wxProcess proc2;
+        proc2.Redirect();
+        CPPUNIT_ASSERT_EQUAL( 0,
+            wxExecute(COMMAND, wxEXEC_SYNC | wxEXEC_NOEVENTS, &proc2) );
+
+        wxStringOutputStream procOutput;
+        CPPUNIT_ASSERT( proc2.GetInputStream() );
+        CPPUNIT_ASSERT_EQUAL( wxSTREAM_EOF,
+            proc2.GetInputStream()->Read(procOutput).GetLastError() );
+
+        wxString output = procOutput.GetString();
+        CPPUNIT_ASSERT_EQUAL( "hi", output.Trim() );
+    }
+}
+
+
+// This class exits the event loop associated with it when the child process
+// terminates.
+class TestAsyncProcess : public wxProcess
+{
+public:
+    wxEXPLICIT TestAsyncProcess()
+    {
+    }
+
+    // may be overridden to be notified about process termination
+    virtual void OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
+    {
+        wxEventLoop::GetActive()->ScheduleExit();
+    }
+
+private:
+    wxDECLARE_NO_COPY_CLASS(TestAsyncProcess);
+};
 
-    wxString str(stdout_stream.GetString());
-    CPPUNIT_ASSERT_EQUAL( "hi", str.Trim() );
+void ExecTestCase::TestAsync()
+{
+    // Test asynchronous execution with no redirection, just to make sure we
+    // get the OnTerminate() call.
+    TestAsyncProcess proc;
+    AsyncInEventLoop asyncInEventLoop;
+
+    CPPUNIT_ASSERT( asyncInEventLoop.DoExecute(
+                       AsyncExec_DontExitLoop,  // proc is expected (inside of its OnTerminate())
+                               // to trigger the exit of the event loop.
+                       COMMAND_NO_OUTPUT, wxEXEC_ASYNC, &proc) != 0 );
 }
 
+void
+ExecTestCase::DoTestAsyncRedirect(const wxString& command,
+                                  CheckStream check,
+                                  const char* expectedContaining)
+{
+    AsyncInEventLoop asyncInEventLoop;
+    TestAsyncProcess proc;
+
+    proc.Redirect();
+
+    CPPUNIT_ASSERT( asyncInEventLoop.DoExecute(
+                       AsyncExec_DontExitLoop,  // proc is expected (inside of its OnTerminate())
+                               // to trigger the exit of the event loop.
+                       command, wxEXEC_ASYNC, &proc) != 0 );
+
+    wxInputStream *streamToCheck = NULL;
+    switch ( check )
+    {
+        case Check_Stdout:
+            streamToCheck = proc.GetInputStream();
+            break;
+
+        case Check_Stderr:
+            streamToCheck = proc.GetErrorStream();
+            break;
+    }
+
+    wxTextInputStream tis(*streamToCheck);
+
+    // Check that the first line of output contains what we expect.
+    CPPUNIT_ASSERT( tis.ReadLine().Contains(expectedContaining) );
+}
+
+void ExecTestCase::TestAsyncRedirect()
+{
+    // Test redirection with reading from the input stream after process termination.
+    DoTestAsyncRedirect(COMMAND, Check_Stdout, "hi");
+
+    // Test redirection with reading from the error stream after process termination.
+    DoTestAsyncRedirect(COMMAND_STDERR, Check_Stderr, "file");
+}
+
+// static
+wxString ExecTestCase::CreateSleepFile(const wxString& basename, int seconds)
+{
+#ifdef __UNIX__
+    static const char* const scriptExt = ".sh";
+
+    // The script text is a format string with a single "%d" appearing in it
+    // which will be replaced by the number of seconds to sleep below.
+    static const char* const scriptText =
+        "sleep %d\n"
+        "echo " SLEEP_END_STRING "\n";
+#elif defined(__WINDOWS__)
+    static const char* const scriptExt = ".bat";
+
+    // Notice that we need to ping N+1 times for it to take N seconds as the
+    // first ping is sent out immediately, without waiting a second.
+    static const char* const scriptText =
+        "@ ping 127.0.0.1 -n 1 > nul\n"
+        "@ ping 127.0.0.1 -n %d > nul\n"
+        "@ echo " SLEEP_END_STRING "\n";
+#else
+    #error "Need code to create sleep file for this platform"
+#endif
+
+    const wxString fnSleep = wxFileName(".", basename, scriptExt).GetFullPath();
+
+    wxFile fileSleep;
+    CPPUNIT_ASSERT
+    (
+        fileSleep.Create(fnSleep, true, wxS_IRUSR | wxS_IWUSR | wxS_IXUSR)
+    );
+
+    fileSleep.Write(wxString::Format(scriptText, seconds));
+
+    return fnSleep;
+}
+
+// static
+wxString ExecTestCase::MakeShellCommand(const wxString& filename)
+{
+    wxString command;
+
+#ifdef __UNIX__
+    command = "/bin/sh " + filename;
+#elif defined(__WINDOWS__)
+    command = wxString::Format("cmd.exe /c \"%s\"", filename);
+#else
+    #error "Need to code to launch shell for this platform"
+#endif
+
+    return command;
+}
+
+void ExecTestCase::TestOverlappedSyncExecute()
+{
+    // Windows Synchronous wxExecute implementation does not currently
+    // support overlapped event loops.  It is still using wxYield, which is
+    // not nestable.  Therefore, this test would fail in Windows.
+    // If someday somebody changes that in Windows, they could use this
+    // test to verify it.
+    //
+    // Because MSW is not yet ready for this test, it may make sense to
+    // separate it out to its own test suite, so we could register it under
+    // "fixme" for Windows, but a real test for Unix.  But that is more work,
+    // so just #ifndefing it here for now.
+    //
+    // Too bad you can't just register one test case of a test suite as a
+    // "fixme".
+#ifndef __WXMSW__
+    // Simple helper delaying the call to wxExecute(): instead of running it
+    // immediately, it runs it when we re-enter the event loop.
+    class DelayedExecuteTimer : public wxTimer
+    {
+    public:
+        DelayedExecuteTimer(const wxString& command, wxArrayString& outputArray)
+            : m_command(command),
+              m_outputArray(outputArray)
+        {
+            // The exact delay doesn't matter, anything short enough will do.
+            StartOnce(10);
+        }
+
+        virtual void Notify()
+        {
+            wxExecute(m_command, m_outputArray);
+        }
+
+    private:
+        wxString m_command;
+        wxArrayString& m_outputArray;
+    };
+
+    // Create two scripts with one of them taking longer than the other one to
+    // execute.
+    const wxString shortSleepFile = CreateSleepFile("shortsleep", 1);
+    wxON_BLOCK_EXIT1( wxRemoveFile, shortSleepFile );
+    const wxString longSleepFile = CreateSleepFile("longsleep", 2);
+    wxON_BLOCK_EXIT1( wxRemoveFile, longSleepFile );
+
+    const wxString shortSleepCommand = MakeShellCommand(shortSleepFile);
+    const wxString longSleepCommand = MakeShellCommand(longSleepFile);
+
+    // Collect the child process output
+    wxArrayString shortSleepOutput,
+                  longSleepOutput;
+
+    // Test that launching a process taking a longer time to run while the
+    // shorter process is running works, i.e. that our outer wxExecute()
+    // doesn't return until both process terminate.
+    DelayedExecuteTimer delayLongSleep(longSleepCommand, longSleepOutput);
+    wxExecute(shortSleepCommand, shortSleepOutput);
+    CPPUNIT_ASSERT( !shortSleepOutput.empty() );
+    CPPUNIT_ASSERT_EQUAL( SLEEP_END_STRING, shortSleepOutput.Last() );
+
+    CPPUNIT_ASSERT( !longSleepOutput.empty() );
+    CPPUNIT_ASSERT_EQUAL( SLEEP_END_STRING, longSleepOutput.Last() );
+
+    // And also that, vice versa, running a short-lived child process that both
+    // starts and ends while a longer-lived parent process is still running
+    // works too.
+    DelayedExecuteTimer delayShortSleep(shortSleepCommand, shortSleepOutput);
+    wxExecute(longSleepCommand, longSleepOutput);
+    CPPUNIT_ASSERT( !shortSleepOutput.empty() );
+    CPPUNIT_ASSERT_EQUAL( SLEEP_END_STRING, shortSleepOutput.Last() );
+
+    CPPUNIT_ASSERT( !longSleepOutput.empty() );
+    CPPUNIT_ASSERT_EQUAL( SLEEP_END_STRING, longSleepOutput.Last() );
+#endif // !__WXMSW__
+}
index 4013df583ebe4796edae59e7acf84db9cd6f29f8..cfeaf4e58d202d730e3fc048085343fcb3a3e549 100644 (file)
@@ -198,6 +198,7 @@ TEST_GUI_OBJECTS =  \
        $(OBJS)\test_gui_evtlooptest.obj \
        $(OBJS)\test_gui_propagation.obj \\r
        $(OBJS)\test_gui_keyboard.obj \\r
+       $(OBJS)\test_gui_exec.obj \
        $(OBJS)\test_gui_fonttest.obj \\r
        $(OBJS)\test_gui_image.obj \\r
        $(OBJS)\test_gui_rawbmp.obj \\r
@@ -953,6 +954,9 @@ $(OBJS)\test_gui_propagation.obj: .\events\propagation.cpp
 $(OBJS)\test_gui_keyboard.obj: .\events\keyboard.cpp\r
        $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\events\keyboard.cpp\r
 \r
+$(OBJS)\test_gui_exec.obj: .\exec\exec.cpp
+       $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\exec\exec.cpp
+
 $(OBJS)\test_gui_fonttest.obj: .\font\fonttest.cpp\r
        $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\font\fonttest.cpp\r
 \r
index 875dd6c0c9e6c7f7c21aba25ce7a3f2c353def57..6f9766096d80bee259721c3c4a20c9e10a406f8c 100644 (file)
@@ -192,6 +192,7 @@ TEST_GUI_OBJECTS =  \
        $(OBJS)\test_gui_evtlooptest.o \
        $(OBJS)\test_gui_propagation.o \\r
        $(OBJS)\test_gui_keyboard.o \\r
+       $(OBJS)\test_gui_exec.o \
        $(OBJS)\test_gui_fonttest.o \\r
        $(OBJS)\test_gui_image.o \\r
        $(OBJS)\test_gui_rawbmp.o \\r
@@ -942,6 +943,9 @@ $(OBJS)\test_gui_propagation.o: ./events/propagation.cpp
 $(OBJS)\test_gui_keyboard.o: ./events/keyboard.cpp\r
        $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<\r
 \r
+$(OBJS)\test_gui_exec.o: ./exec/exec.cpp
+       $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\test_gui_fonttest.o: ./font/fonttest.cpp\r
        $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<\r
 \r
index 09066b24626c4ba57720a307d0b34da8e2054fe9..e0e9237a10fd5c76c9449f5cac34bfc4d42a02bf 100644 (file)
@@ -195,6 +195,7 @@ TEST_GUI_OBJECTS =  \
        $(OBJS)\test_gui_evtlooptest.obj \
        $(OBJS)\test_gui_propagation.obj \\r
        $(OBJS)\test_gui_keyboard.obj \\r
+       $(OBJS)\test_gui_exec.obj \
        $(OBJS)\test_gui_fonttest.obj \\r
        $(OBJS)\test_gui_image.obj \\r
        $(OBJS)\test_gui_rawbmp.obj \\r
@@ -1093,6 +1094,9 @@ $(OBJS)\test_gui_propagation.obj: .\events\propagation.cpp
 $(OBJS)\test_gui_keyboard.obj: .\events\keyboard.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\events\keyboard.cpp\r
 \r
+$(OBJS)\test_gui_exec.obj: .\exec\exec.cpp
+       $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\exec\exec.cpp
+
 $(OBJS)\test_gui_fonttest.obj: .\font\fonttest.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\font\fonttest.cpp\r
 \r
index 505bfa323205d8d4bf147573e2785cca440113c6..916f203450487f1159f1c4777d2e93c9dd3fa547 100644 (file)
@@ -467,6 +467,7 @@ TEST_GUI_OBJECTS =  &
        $(OBJS)\test_gui_evtlooptest.obj &
        $(OBJS)\test_gui_propagation.obj &\r
        $(OBJS)\test_gui_keyboard.obj &\r
+       $(OBJS)\test_gui_exec.obj &
        $(OBJS)\test_gui_fonttest.obj &\r
        $(OBJS)\test_gui_image.obj &\r
        $(OBJS)\test_gui_rawbmp.obj &\r
@@ -1002,6 +1003,9 @@ $(OBJS)\test_gui_propagation.obj :  .AUTODEPEND .\events\propagation.cpp
 $(OBJS)\test_gui_keyboard.obj :  .AUTODEPEND .\events\keyboard.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<\r
 \r
+$(OBJS)\test_gui_exec.obj :  .AUTODEPEND .\exec\exec.cpp
+       $(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<
+
 $(OBJS)\test_gui_fonttest.obj :  .AUTODEPEND .\font\fonttest.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<\r
 \r
index afe4637ef0cb5e6635a72a698fc7dd7789f0f2a6..6fc4e1802a951d638180398ba5c1be7e11290708 100644 (file)
             events/evtlooptest.cpp
             events/propagation.cpp
             events/keyboard.cpp
+            <!--
+                And duplicate this one too as wxExecute behaves differently in
+                console and GUI applications.
+             -->
+            exec/exec.cpp
             font/fonttest.cpp
             image/image.cpp
             image/rawbmp.cpp
index 287a816edce875461adc947922b5b471f1239f1f..7b919a77555e20a27bc633fed14e35c57823a90b 100644 (file)
@@ -27,13 +27,13 @@ CFG=test - Win32 Debug
 # PROP AllowPerConfigDependencies 0\r
 # PROP Scc_ProjName ""\r
 # PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "test - Win32 DLL Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "test - Win32 DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
 # PROP BASE Output_Dir "vc_mswudll"\r
 # PROP BASE Intermediate_Dir "vc_mswudll\test"\r
 # PROP BASE Target_Dir ""\r
index 14a6c42d77afbd6a43274e34828e8d92438a53f2..ff7a82e362ec96d91839fc56d3b50a523ac8fbd8 100644 (file)
@@ -27,13 +27,13 @@ CFG=test_gui - Win32 Debug
 # PROP AllowPerConfigDependencies 0\r
 # PROP Scc_ProjName ""\r
 # PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "test_gui - Win32 DLL Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "test_gui - Win32 DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
 # PROP BASE Output_Dir "vc_mswudll"\r
 # PROP BASE Intermediate_Dir "vc_mswudll\test_gui"\r
 # PROP BASE Target_Dir ""\r
@@ -233,6 +233,10 @@ SOURCE=.\events\evtlooptest.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\exec\exec.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\font\fonttest.cpp\r
 # End Source File\r
 # Begin Source File\r
@@ -378,16 +382,16 @@ SOURCE=.\controls\richtextctrltest.cpp
 # Begin Source File\r
 \r
 SOURCE=.\..\samples\sample.rc\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\controls\searchctrltest.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\misc\selstoretest.cpp\r
-# End Source File\r
-# Begin Source File\r
+# End Source File
+# Begin Source File
+
+SOURCE=.\controls\searchctrltest.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\selstoretest.cpp
+# End Source File
+# Begin Source File
 \r
 SOURCE=.\window\setsize.cpp\r
 # End Source File\r
index 012dcdaf5a8e51c63bb676f722d8aa090318e2c2..7b39bc6cdb4940229c8d6cd134350150303c87aa 100644 (file)
                        <File\r
                                RelativePath=".\events\evtlooptest.cpp">\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\exec\exec.cpp">\r
+                       </File>\r
                        <File\r
                                RelativePath=".\font\fonttest.cpp">\r
                        </File>\r
index a9abb0833fcc14e452074421517857bc2ac481d3..dbf7879e777c3cda0ac2030e3626d76a7a911a5e 100644 (file)
                                RelativePath=".\events\evtlooptest.cpp"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\exec\exec.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\font\fonttest.cpp"\r
                                >\r
index 640de7a67d630cec553191bb51a895ba27efc98c..fe1efbf3486da1fd9687cfb43d713314c8320353 100644 (file)
                                RelativePath=".\events\evtlooptest.cpp"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\exec\exec.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\font\fonttest.cpp"\r
                                >\r