lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [5995] Augment automated GUI test


From: Greg Chicares
Subject: [lmi-commits] [5995] Augment automated GUI test
Date: Sat, 25 Oct 2014 14:42:27 +0000

Revision: 5995
          http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=5995
Author:   chicares
Date:     2014-10-25 14:42:26 +0000 (Sat, 25 Oct 2014)
Log Message:
-----------
Augment automated GUI test

Modified Paths:
--------------
    lmi/trunk/ChangeLog
    lmi/trunk/Makefile.am
    lmi/trunk/main_wx_test.cpp
    lmi/trunk/objects.make
    lmi/trunk/skeleton.hpp

Added Paths:
-----------
    lmi/trunk/wx_test_about_version.cpp
    lmi/trunk/wx_test_benchmark_census.cpp
    lmi/trunk/wx_test_calculation_summary.cpp
    lmi/trunk/wx_test_case.hpp
    lmi/trunk/wx_test_config_settings.cpp
    lmi/trunk/wx_test_create_open.cpp
    lmi/trunk/wx_test_default_input.cpp
    lmi/trunk/wx_test_default_update.cpp
    lmi/trunk/wx_test_expiry_dates.cpp
    lmi/trunk/wx_test_extract.cpp
    lmi/trunk/wx_test_input_sequences.cpp
    lmi/trunk/wx_test_input_validation.cpp
    lmi/trunk/wx_test_mvc_dialog.hpp
    lmi/trunk/wx_test_new.hpp
    lmi/trunk/wx_test_paste_census.cpp
    lmi/trunk/wx_test_pdf_create.cpp
    lmi/trunk/wx_test_statusbar.hpp
    lmi/trunk/wx_test_validate_output.cpp

Modified: lmi/trunk/ChangeLog
===================================================================
--- lmi/trunk/ChangeLog 2014-10-21 13:58:38 UTC (rev 5994)
+++ lmi/trunk/ChangeLog 2014-10-25 14:42:26 UTC (rev 5995)
@@ -34353,3 +34353,29 @@
   expression_template_0_test.cpp
 Improve documentation.
 
+20141025T1442Z <address@hidden> [533]
+
+  Makefile.am
+  main_wx_test.cpp
+  objects.make
+  skeleton.hpp
+  wx_test_about_version.cpp       [new file]
+  wx_test_benchmark_census.cpp    [new file]
+  wx_test_calculation_summary.cpp [new file]
+  wx_test_case.hpp                [new file]
+  wx_test_config_settings.cpp     [new file]
+  wx_test_create_open.cpp         [new file]
+  wx_test_default_input.cpp       [new file]
+  wx_test_default_update.cpp      [new file]
+  wx_test_expiry_dates.cpp        [new file]
+  wx_test_extract.cpp             [new file]
+  wx_test_input_sequences.cpp     [new file]
+  wx_test_input_validation.cpp    [new file]
+  wx_test_mvc_dialog.hpp          [new file]
+  wx_test_new.hpp                 [new file]
+  wx_test_paste_census.cpp        [new file]
+  wx_test_pdf_create.cpp          [new file]
+  wx_test_statusbar.hpp           [new file]
+  wx_test_validate_output.cpp     [new file]
+Augment automated GUI test.
+

Modified: lmi/trunk/Makefile.am
===================================================================
--- lmi/trunk/Makefile.am       2014-10-21 13:58:38 UTC (rev 5994)
+++ lmi/trunk/Makefile.am       2014-10-25 14:42:26 UTC (rev 5995)
@@ -255,6 +255,20 @@
     $(BOOST_LIBS)
 
 wx_test_SOURCES = \
+  wx_test_about_version.cpp \
+  wx_test_benchmark_census.cpp \
+  wx_test_calculation_summary.cpp \
+  wx_test_config_settings.cpp \
+  wx_test_create_open.cpp \
+  wx_test_default_input.cpp \
+  wx_test_default_update.cpp \
+  wx_test_expiry_dates.cpp \
+  wx_test_extract.cpp \
+  wx_test_input_sequences.cpp \
+  wx_test_input_validation.cpp \
+  wx_test_paste_census.cpp \
+  wx_test_pdf_create.cpp \
+  wx_test_validate_output.cpp \
   main_wx_test.cpp
 wx_test_CXXFLAGS = $(AM_CXXFLAGS) $(WX_CXXFLAGS)
 wx_test_LDADD = \

Modified: lmi/trunk/main_wx_test.cpp
===================================================================
--- lmi/trunk/main_wx_test.cpp  2014-10-21 13:58:38 UTC (rev 5994)
+++ lmi/trunk/main_wx_test.cpp  2014-10-25 14:42:26 UTC (rev 5995)
@@ -26,73 +26,427 @@
 #   pragma hdrstop
 #endif
 
-#include "assert_lmi.hpp"
+#include "alert.hpp"
 #include "force_linking.hpp"
+#include "handle_exceptions.hpp"        // stealth_exception
 #include "main_common.hpp"              // initialize_application()
 #include "msw_workarounds.hpp"
+#include "obstruct_slicing.hpp"
 #include "path_utility.hpp"             // initialize_filesystem()
 #include "skeleton.hpp"
-#include "version.hpp"
+#include "uncopyable_lmi.hpp"
+#include "wx_test_case.hpp"
 
-#include <wx/dialog.h>
+#include <wx/fileconf.h>
+#include <wx/frame.h>
 #include <wx/init.h>                    // wxEntry()
-#include <wx/testing.h>
-#include <wx/uiaction.h>
+#include <wx/stopwatch.h>
+#include <wx/wfstream.h>
 
+#include <boost/scoped_ptr.hpp>
+
+#include <algorithm>                    // std::sort()
+#include <cstring>                      // std::strcmp()
+#include <exception>                    // uncaught_exception()
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <utility>                      // std::pair
+#include <vector>
+
 LMI_FORCE_LINKING_EX_SITU(file_command_wx)
 LMI_FORCE_LINKING_EX_SITU(progress_meter_wx)
 LMI_FORCE_LINKING_EX_SITU(system_command_wx)
 
+#if !wxCHECK_VERSION(3,1,0)
+#   error wxWidgets 3.1.0 or later is required for the test suite.
+#endif
+
 class SkeletonTest;
 DECLARE_APP(SkeletonTest)
 
-class application_test
+/// Implement this normally unimplemented function.
+///
+/// The implementation of this constructor is not provided to prevent
+/// production code from creating objects of this type, but we do need to use
+/// this exception here, for the special testing purposes, so explicitly opt in
+/// into using it by provide this implementation.
+stealth_exception::stealth_exception(std::string const& what_arg)
+    :std::runtime_error(what_arg)
+{}
+
+namespace
 {
+
+/// Exception thrown if a wxWidgets assertion fails during the test code
+/// execution. It must inherit from stealth_exception to avoid this exception
+/// being caught, reported and ignored by well-meaning but harmful in this case
+/// exception handling code elsewhere.
+///
+/// Implicitly-declared special member functions do the right thing.
+
+class test_assertion_failure_exception
+    :public stealth_exception
+{
   public:
-    static void test()
+    test_assertion_failure_exception
+        (wxChar const* msg
+        ,wxChar const* file
+        ,int line
+        ,wxChar const* func
+        )
+        :stealth_exception
+            (wxString::Format
+                ("Assertion failure: %s [file %s, line %d, in %s()]."
+                ,msg
+                ,file
+                ,line
+                ,func
+                ).ToStdString()
+            )
         {
-        test_about_dialog_version();
         }
+};
 
+/// Run the tests.
+///
+/// This is a simple Meyers singleton.
+class application_test
+    :        private lmi::uncopyable  <application_test>
+    ,virtual private obstruct_slicing <application_test>
+{
+  public:
+    static application_test& instance();
+
+    // Check the command line for the test-specific options, handle them and
+    // remove them from argv.
+    //
+    // Return false if the program execution shouldn't continue, currently this
+    // is only the case if the "list" option was specified requesting just to
+    // list the available tests.
+    bool process_command_line(int& argc, char* argv[]);
+
+    // Run all the tests that were configured to be executed (all by default).
+    //
+    // This function consumes all the exceptions thrown during its execution
+    // and never throws itself.
+    //
+    // Return the number of tests executed as the first pair component and the
+    // number of failed tests as the second component.
+    std::pair<int, int> run() /* noexcept */;
+
+    // Used by LMI_WX_TEST_CASE() macro to register the individual test cases.
+    void add_test(wx_base_test_case* test);
+
+    // Used by tests to retrieve their configuration parameters.
+    wxConfigBase const& get_config_for(char const* name);
+
   private:
-    static void test_about_dialog_version();
-};
+    application_test();
 
-void application_test::test_about_dialog_version()
-{
-    struct expect_about_dialog : public wxExpectModalBase<wxDialog>
+    // Sort all tests in alphabetical order of their names.
+    void sort_tests();
+
+    // List all tests on standard output.
+    void list_tests();
+
+    // Include of exclude the given test depending on the value given on the
+    // command line.
+    void process_test_name(char const* name);
+
+    // A test can be explicitly included, explicitly excluded or not
+    // mentioned, in which case it will run if all tests are ran by default.
+    enum test_run
+        {run_yes
+        ,run_no
+        ,run_default
+        };
+
+    /// Contains everything we need to store for an individual test.
+    struct test_descriptor
     {
-        virtual int OnInvoked(wxDialog* d) const
+        // The pointer must be non-NULL but we don't take ownership of it.
+        test_descriptor(wx_base_test_case* test)
+            :test(test)
+            ,run(run_default)
+        {
+        }
+
+        char const* get_name() const { return test->get_name(); }
+
+        void run_test() const { test->run(); }
+
+        // Comparator used for sorting the tests.
+        static bool Compare
+            (test_descriptor const& t1
+            ,test_descriptor const& t2)
             {
-            LMI_ASSERT(0 != d);
-            LMI_ASSERT(d->GetTitle().EndsWith(LMI_VERSION));
-            return wxID_OK;
+            return std::strcmp(t1.get_name(), t2.get_name()) < 0;
             }
+
+        wx_base_test_case* test;
+        test_run run;
     };
 
-    wxUIActionSimulator z;
-    z.KeyDown('h', wxMOD_ALT);
-    z.KeyUp  ('h', wxMOD_ALT);
-    z.KeyDown('a'           );
-    z.KeyUp  ('a'           );
-    wxTEST_DIALOG
-        (wxYield()
-        ,expect_about_dialog()
-        );
+    std::vector<test_descriptor> tests_;
+
+    boost::scoped_ptr<wxFileConfig> config_;
+
+    bool run_all_;
+};
+
+application_test::application_test()
+    :run_all_(true)
+{
 }
 
+application_test& application_test::instance()
+{
+    static application_test z;
+    return z;
+}
+
+void application_test::process_test_name(char const* name)
+{
+    // A test can be specified either as "test" to run it, or "-test" to avoid
+    // running it, check which one have we got.
+    test_run run;
+    if (name[0] == '-')
+        {
+        run = run_no;
+        name++; // Skip the leading minus sign.
+        }
+    else
+        {
+        // If some test is explicitly requested, all the other ones are
+        // implicitly disabled, otherwise it wouldn't make sense.
+        run_all_ = false;
+        run = run_yes;
+        }
+
+    bool any_tests_matched = false;
+
+    typedef std::vector<test_descriptor>::iterator tdi;
+    for(tdi i = tests_.begin(); i != tests_.end(); ++i)
+        {
+        if (wxString(i->get_name()).Matches(name))
+            {
+            i->run = run;
+            any_tests_matched = true;
+            }
+        }
+
+    if (!any_tests_matched)
+        {
+        warning()
+            << "Test specification '"
+            << name
+            << "', didn't match any tests.\n"
+            << "Use --list command line option to list all tests."
+            << std::flush
+            ;
+        }
+}
+
+// Remove the argument at the given (assumed valid) position from (argc, argv).
+void remove_arg(int n, int& argc, char* argv[])
+{
+    // We include argv[argc] in the elements being copied, this guarantees that
+    // the array remains 0-terminated.
+    std::memmove(argv + n, argv + n + 1, (argc - n)*sizeof(char*));
+
+    argc--;
+}
+
+bool application_test::process_command_line(int& argc, char* argv[])
+{
+    // This variable is used both as a flag indicating that the last option was
+    // the one selecting the test to run and so must be followed by the test
+    // name, but also for the diagnostic message at the end of this function.
+    char const* last_test_option = 0;
+
+    for(int n = 1; n < argc; )
+        {
+        char const* const arg = argv[n];
+
+        if (last_test_option)
+            {
+            last_test_option = 0;
+            process_test_name(arg);
+            remove_arg(n, argc, argv);
+            continue;
+            }
+        else if
+            (  0 == std::strcmp(arg, "-l")
+            || 0 == std::strcmp(arg, "--list")
+            )
+            {
+            list_tests();
+            return false;
+            }
+        else if
+            (  0 == std::strcmp(arg, "-t")
+            || 0 == std::strcmp(arg, "--test")
+            )
+            {
+            last_test_option = arg;
+            remove_arg(n, argc, argv);
+            }
+        else
+            {
+            n++;
+            }
+        }
+
+    if (last_test_option)
+        {
+        warning()
+            << "Option '"
+            << last_test_option
+            << "' must be followed by the test name."
+            << std::flush
+            ;
+        }
+
+    return true;
+}
+
+std::pair<int, int> application_test::run()
+{
+    // Always run the tests in the same, predictable order (we may want to add
+    // a "random shuffle" option later, but even then predictable behaviour
+    // should arguably remain the default).
+    sort_tests();
+
+    std::pair<int, int> results(0, 0);
+
+    // Indent the test status reports to make them stand out.
+    char const* const indent = "    ";
+
+    typedef std::vector<test_descriptor>::const_iterator ctdi;
+    for(ctdi i = tests_.begin(); i != tests_.end(); ++i)
+        {
+        if ((run_all_ && i->run != run_no) || i->run == run_yes)
+            {
+            std::string error;
+            results.first++;
+
+            try
+                {
+                wxStopWatch sw;
+                i->run_test();
+                wxLogMessage("%s%s: ok (%ldms)", indent, i->get_name(), 
sw.Time());
+                }
+            catch(std::exception const& e)
+                {
+                error = e.what();
+                }
+            catch(...)
+                {
+                error = "unknown exception";
+                }
+
+            if (!error.empty())
+                {
+                results.second++;
+
+                // When logging to a log window, it's better to have everything
+                // on a single line to avoid breaking the output structure.
+                wxString one_line_error(error);
+                one_line_error.Replace("\n", " ");
+
+                wxLogMessage
+                    ("%s%s: ERROR (%s)"
+                    ,indent
+                    ,i->get_name()
+                    ,one_line_error
+                    );
+                }
+            }
+        }
+
+    return results;
+}
+
+void application_test::add_test(wx_base_test_case* test)
+{
+    tests_.push_back(test_descriptor(test));
+}
+
+void application_test::sort_tests()
+{
+    std::sort(tests_.begin(), tests_.end(), test_descriptor::Compare);
+}
+
+void application_test::list_tests()
+{
+    sort_tests();
+
+    std::cerr << "Available tests:\n";
+
+    typedef std::vector<test_descriptor>::const_iterator ctdi;
+    for(ctdi i = tests_.begin(); i != tests_.end(); ++i)
+        {
+        std::cerr << '\t' << i->get_name() << '\n';
+        }
+
+    std::cerr << tests_.size() << " test cases.\n";
+}
+
+wxConfigBase const& application_test::get_config_for(char const* name)
+{
+    if(!config_)
+        {
+        wxFFileInputStream is("wx_test.conf", "r");
+        config_.reset(new wxFileConfig(is));
+        }
+
+    config_->SetPath(wxString("/") + name);
+
+    return *config_;
+}
+
+} // Unnamed namespace.
+
+wx_base_test_case::wx_base_test_case(char const* name)
+    :m_name(name)
+{
+    application_test::instance().add_test(this);
+}
+
+wxConfigBase const& wx_base_test_case::config() const
+{
+    return application_test::instance().get_config_for(get_name());
+}
+
 // Application to drive the tests
 class SkeletonTest : public Skeleton
 {
   public:
-    SkeletonTest() {}
+    SkeletonTest()
+        :is_running_tests_(false)
+    {
+    }
 
   protected:
     // wxApp overrides.
-    virtual bool OnInit();
+    virtual bool OnInit                 ();
+    virtual bool OnExceptionInMainLoop  ();
+    virtual bool StoreCurrentException  ();
+    virtual void RethrowStoredException ();
+    virtual void OnAssertFailure
+        (wxChar const* file
+        ,int line
+        ,wxChar const* func
+        ,wxChar const* cond
+        ,wxChar const* msg
+        );
 
   private:
     void RunTheTests();
+
+    std::string runtime_error_;
+    bool is_running_tests_;
 };
 
 IMPLEMENT_APP_NO_MAIN(SkeletonTest)
@@ -112,10 +466,127 @@
     return true;
 }
 
+bool SkeletonTest::StoreCurrentException()
+{
+    try
+        {
+        throw;
+        }
+    catch (std::runtime_error const& e)
+        {
+        runtime_error_ = e.what();
+        return true;
+        }
+
+    return false;
+}
+
+void SkeletonTest::RethrowStoredException()
+{
+    if (!runtime_error_.empty())
+        {
+        std::runtime_error const e(runtime_error_);
+        runtime_error_.clear();
+        throw e;
+        }
+}
+
+bool SkeletonTest::OnExceptionInMainLoop()
+{
+    if (is_running_tests_)
+        {
+        // Don't let the base class catch, report and ignore the exceptions
+        // that happen while running the tests, we need to ensure that the test
+        // fails as the result of assert happening during its run.
+        throw;
+        }
+
+    return Skeleton::OnExceptionInMainLoop();
+}
+
+void SkeletonTest::OnAssertFailure
+    (wxChar const* file
+    ,int line
+    ,wxChar const* func
+    ,wxChar const* cond
+    ,wxChar const* msg
+    )
+{
+    // Assertion during a test run counts as test failure but avoid throwing if
+    // another exception is already in flight as this would just result in the
+    // program termination without any useful information about the reason of
+    // the failure whatsoever.
+    if (is_running_tests_ && !std::uncaught_exception())
+        {
+        throw test_assertion_failure_exception(msg ? msg : cond, file, line, 
func);
+        }
+    else
+        {
+        Skeleton::OnAssertFailure(file, line, func, cond, msg);
+        }
+}
+
 void SkeletonTest::RunTheTests()
 {
-    application_test::test();
-    ExitMainLoop();
+    // Create log window for output that should be checked by the user.
+    class LogWindow : public wxLogWindow
+    {
+      public:
+        LogWindow() : wxLogWindow(NULL, "Log Messages", true, false) {}
+        virtual bool OnFrameClose(wxFrame* frame)
+        {
+            wxTheApp->ExitMainLoop();
+            return wxLogWindow::OnFrameClose(frame);
+        }
+    };
+    LogWindow* const log = new LogWindow();
+
+    wxWindow* const mainWin = GetTopWindow();
+    mainWin->SetFocus();
+
+    wxStopWatch sw;
+    wxLogMessage("Starting automatic tests:");
+
+    // Notice that it is safe to use simple variable assignment here instead of
+    // some RAII-based pattern because of application_test::run() noexcept
+    // guarantee.
+    is_running_tests_ = true;
+    std::pair<int, int> const results = application_test::instance().run();
+    is_running_tests_ = false;
+
+    if (results.first == 0)
+        {
+        wxLogMessage("WARNING: no tests have been executed.");
+        }
+    else if (results.second == 0)
+        {
+        wxLogMessage
+            ("SUCCESS: %d tests successfully completed in %ldms."
+            ,results.first
+            ,sw.Time()
+            );
+        }
+    else
+        {
+        wxLogMessage
+            ("FAILURE: %d out of %d tests failed."
+            ,results.second
+            ,results.first
+            );
+        }
+
+    // We want to show log output after the tests finished running and hide the
+    // app window, which is no longer in use. This doesn't work out of the box,
+    // because the main window is set application's top window and closing it
+    // terminates the app. LogWindow's window, on the other hand, doesn't keep
+    // the app running because it returns false from ShouldPreventAppExit().
+    // This code (together with LogWindow::OnFrameClose above) does the right
+    // thing: close the main window and keep running until the user closes the
+    // log window.
+    log->GetFrame()->Maximize();
+    log->GetFrame()->SetFocus();
+    SetExitOnFrameDelete(false);
+    mainWin->Close();
 }
 
 int main(int argc, char* argv[])
@@ -125,6 +596,15 @@
 #ifdef LMI_MSW
     MswDllPreloader::instance().PreloadDesignatedDlls();
 #endif
+
+    // We need to handle test-specific options and remove them from argv before
+    // letting wxEntry() instantiate Skeleton application object that would
+    // give an error for these, unknown to it, options.
+    if (!application_test::instance().process_command_line(argc, argv))
+        {
+        return 0;
+        }
+
     return wxEntry(argc, argv);
 }
 

Modified: lmi/trunk/objects.make
===================================================================
--- lmi/trunk/objects.make      2014-10-21 13:58:38 UTC (rev 5994)
+++ lmi/trunk/objects.make      2014-10-25 14:42:26 UTC (rev 5995)
@@ -356,6 +356,20 @@
 
 wx_test_objects := \
   main_wx_test.o \
+  wx_test_about_version.o \
+  wx_test_benchmark_census.o \
+  wx_test_calculation_summary.o \
+  wx_test_config_settings.o \
+  wx_test_create_open.o \
+  wx_test_default_input.o \
+  wx_test_default_update.o \
+  wx_test_expiry_dates.o \
+  wx_test_extract.o \
+  wx_test_input_sequences.o \
+  wx_test_input_validation.o \
+  wx_test_paste_census.o \
+  wx_test_pdf_create.o \
+  wx_test_validate_output.o \
 
 ifneq (,$(RC))
   lmi_wx_objects  += lmi_msw_res.o

Modified: lmi/trunk/skeleton.hpp
===================================================================
--- lmi/trunk/skeleton.hpp      2014-10-21 13:58:38 UTC (rev 5994)
+++ lmi/trunk/skeleton.hpp      2014-10-25 14:42:26 UTC (rev 5995)
@@ -63,7 +63,8 @@
 
   protected:
     // wxApp overrides that are further overridden in gui test.
-    virtual bool OnInit();
+    virtual bool OnInit                ();
+    virtual bool OnExceptionInMainLoop ();
 
   private:
     wxMenuBar* AdjustMenus(wxMenuBar*);
@@ -114,9 +115,8 @@
     void UponWindowTileVertically         (wxCommandEvent&);
 
     // wxApp overrides.
-    virtual bool OnExceptionInMainLoop ();
-    virtual int  OnExit                ();
-    virtual void OnUnhandledException  ();
+    virtual int  OnExit               ();
+    virtual void OnUnhandledException ();
 
     bool ProcessCommandLine(int argc, char* argv[]);
     void UpdateViews();

Added: lmi/trunk/wx_test_about_version.cpp
===================================================================
--- lmi/trunk/wx_test_about_version.cpp                         (rev 0)
+++ lmi/trunk/wx_test_about_version.cpp 2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,58 @@
+// Version number test case for the GUI test suite.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "wx_test_case.hpp"
+#include "version.hpp"
+
+#include <wx/dialog.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+LMI_WX_TEST_CASE(about_dialog_version)
+{
+    struct expect_about_dialog : public wxExpectModalBase<wxDialog>
+    {
+        virtual int OnInvoked(wxDialog* d) const
+            {
+            LMI_ASSERT(0 != d);
+            LMI_ASSERT(d->GetTitle().EndsWith(LMI_VERSION));
+            return wxID_OK;
+            }
+    };
+
+    wxUIActionSimulator z;
+    z.KeyDown('h', wxMOD_ALT);
+    z.KeyUp  ('h', wxMOD_ALT);
+    z.KeyDown('a'           );
+    z.KeyUp  ('a'           );
+    wxTEST_DIALOG
+        (wxYield()
+        ,expect_about_dialog()
+        );
+}


Property changes on: lmi/trunk/wx_test_about_version.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_benchmark_census.cpp
===================================================================
--- lmi/trunk/wx_test_benchmark_census.cpp                              (rev 0)
+++ lmi/trunk/wx_test_benchmark_census.cpp      2014-10-25 14:42:26 UTC (rev 
5995)
@@ -0,0 +1,180 @@
+// Test benchmarking census operations.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "wx_test_case.hpp"
+#include "wx_test_statusbar.hpp"
+#include "uncopyable_lmi.hpp"
+
+#include <wx/confbase.h>
+#include <wx/dialog.h>
+#include <wx/frame.h>
+#include <wx/log.h>
+#include <wx/scopeguard.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+#include <cmath>                    // std::fabs()
+
+namespace
+{
+
+class census_benchmark
+    :private lmi::uncopyable<census_benchmark>
+{
+  public:
+    explicit census_benchmark(wxString const& name, wxString const& path)
+        :status_(get_main_window_statusbar())
+        ,name_(name)
+        {
+        wxUIActionSimulator z;
+        z.Char('o', wxMOD_CONTROL); // "File|Open"
+        wxTEST_DIALOG
+            (wxYield()
+            ,wxExpectModal<wxFileDialog>(path)
+            );
+        wxYield();
+        }
+
+    void time_operation
+        (char const* operation
+        ,long time_expected
+        ,char key
+        ,int mod
+        )
+        {
+        wxUIActionSimulator z;
+        z.Char(key, mod);
+        wxYield();
+
+        wxString const status_text = status_.GetStatusText();
+        wxString ms_text;
+        LMI_ASSERT(status_text.EndsWith(" milliseconds", &ms_text));
+
+        long time_real;
+        LMI_ASSERT(ms_text.ToLong(&time_real));
+
+        // Compare the difference with the expected time if it's specified.
+        wxString delta;
+        if (time_expected)
+            {
+            double const diff_in_percents =
+                100*(time_real - time_expected)
+                    / static_cast<double>(time_expected);
+
+            delta.Printf("%+.2f%%", diff_in_percents);
+
+            LMI_ASSERT_WITH_MSG
+                (std::fabs(diff_in_percents) < 10
+                ,wxString::Format
+                    (
+                    "expected %ldms, but actually took %ldms, i.e. %s"
+                    ,time_expected
+                    ,time_real
+                    ,delta
+                    )
+                );
+            }
+        else
+            {
+            delta = "not specified";
+            }
+
+        wxLogMessage
+            ("%s for %s: %ldms elapsed (expected %s)"
+            ,operation
+            ,name_
+            ,time_real
+            ,delta
+            );
+        }
+
+    void close_window()
+        {
+        wxUIActionSimulator z;
+        z.Char('l', wxMOD_CONTROL); // "File|Close"
+        }
+
+    ~census_benchmark()
+        {
+        // Close the census window opened in the ctor itself.
+        close_window();
+        }
+
+  private:
+    wxStatusBar const& status_;
+    wxString const name_;
+};
+
+} // Unnamed namespace.
+
+LMI_WX_TEST_CASE(benchmark_census)
+{
+    wxConfigBase const& c = config();
+
+    // Read the timing parameters.
+    long const time_run = c.ReadLong("time_run", 0);
+    long const time_disk = c.ReadLong("time_disk", 0);
+    long const time_spreadsheet = c.ReadLong("time_spreadsheet", 0);
+
+    // The censuses to benchmark are specified by the subgroups of the config
+    // file, so iterate over all of them.
+    wxString name;
+    long z;
+    for(bool ok = c.GetFirstGroup(name, z); ok; ok = c.GetNextGroup(name, z))
+        {
+        census_benchmark b(name, c.Read(name + "/path"));
+
+        {
+        // Ensure that the window doesn't stay opened (and possibly affects
+        // negatively the subsequent tests) even if this test fails.
+        wxON_BLOCK_EXIT_OBJ0(b, census_benchmark::close_window);
+
+        b.time_operation
+            ("Run case"
+            ,time_run
+            ,'r'
+            ,wxMOD_CONTROL | wxMOD_SHIFT
+            );
+        }
+
+        b.time_operation
+            ("Print to disk"
+            ,time_disk
+            ,'k'
+            ,wxMOD_CONTROL | wxMOD_SHIFT
+            );
+
+        b.time_operation
+            ("Print to spreadsheet"
+            ,time_spreadsheet
+            ,'h'
+            ,wxMOD_CONTROL | wxMOD_SHIFT
+            );
+        }
+}


Property changes on: lmi/trunk/wx_test_benchmark_census.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_calculation_summary.cpp
===================================================================
--- lmi/trunk/wx_test_calculation_summary.cpp                           (rev 0)
+++ lmi/trunk/wx_test_calculation_summary.cpp   2014-10-25 14:42:26 UTC (rev 
5995)
@@ -0,0 +1,297 @@
+// Test calculation summary features.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "wx_test_case.hpp"
+#include "wx_test_mvc_dialog.hpp"
+#include "wx_test_new.hpp"
+#include "wx_utility.hpp"
+
+#include <wx/ffile.h>
+#include <wx/html/htmlpars.h>
+#include <wx/html/htmlwin.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+#include <cstddef>                          // std::size_t
+
+namespace
+{
+
+struct name_and_title
+{
+    char const* name;
+    char const* title;
+};
+
+// Names and titles of the columns used by default.
+name_and_title const default_columns_info[] =
+    {{ "PolicyYear"             , "Policy Year"                 }
+    ,{ "Outlay"                 , "Net Outlay"                  }
+    ,{ "AcctVal_Current"        , "Curr Account Value"          }
+    ,{ "CSVNet_Current"         , "Curr Net Cash Surr Value"    }
+    ,{ "EOYDeathBft_Current"    , "Curr EOY Death Benefit"      }
+    };
+
+std::size_t const number_of_default_columns
+    = sizeof default_columns_info / sizeof(default_columns_info[0]);
+
+// Names and titles of the columns used when not using the built-in calculation
+// summary.
+name_and_title const custom_columns_info[] =
+    {{ "PolicyYear"             , "Policy Year"                 }
+    ,{ "AttainedAge"            , "Attained Age"                }
+    ,{ "Outlay"                 , "Net Outlay"                  }
+    ,{ "CSVNet_Current"         , "Curr Net Cash Surr Value"    }
+    ,{ "AcctVal_Current"        , "Curr Account Value"          }
+    ,{ "CSVNet_Guaranteed"      , "Guar Net Cash Surr Value"    }
+    ,{ "AcctVal_Guaranteed"     , "Guar Account Value"          }
+    ,{ "EOYDeathBft_Current"    , "Curr EOY Death Benefit"      }
+    ,{ "EOYDeathBft_Guaranteed" , "Guar EOY Death Benefit"      }
+    ,{ "NetWD"                  , "Withdrawal"                  }
+    ,{ "NewCashLoan"            , "Annual Loan"                 }
+    ,{ "LoanIntAccrued_Current" , "Curr Loan Int Accrued"       }
+    };
+
+std::size_t const number_of_custom_columns
+    = sizeof custom_columns_info / sizeof(custom_columns_info[0]);
+
+// Special name used when the column is not used at all.
+char const* const magic_null_column_name = "[none]";
+
+// Change the calculation summary settings in the preferences dialog to use, or
+// not use, the built-in defaults.
+void use_builtin_calculation_summary(bool b)
+{
+    wxUIActionSimulator ui;
+    ui.Char('f', wxMOD_CONTROL);    // "File|Preferences"
+
+    class ChangeCalculationSummaryInPreferencesDialog
+        :public ExpectMvcDialog
+    {
+      public:
+        ChangeCalculationSummaryInPreferencesDialog
+            (bool use_builtin_summary)
+            :use_builtin_summary_(use_builtin_summary)
+            {
+            }
+
+        virtual void DoRunDialog(MvcController* dialog) const
+            {
+            wxUIActionSimulator ui;
+
+            // Go to the "Use built-in calculation summary" checkbox.
+            ui.Char(WXK_TAB);
+            wxYield();
+
+            // Disable the checkbox initially as we need it to be disabled to
+            // change the values of the column controls.
+            ui.Char('-');
+            wxYield();
+
+            DoUpdateDialogUI(dialog);
+
+            // Update the columns controls when using them.
+            for(std::size_t n = 0; n < number_of_custom_columns; ++n)
+                {
+                ui.Char(WXK_TAB);
+                wxYield();
+
+                wxString const column_name
+                    (use_builtin_summary_
+                    ? magic_null_column_name
+                    : custom_columns_info[n].name
+                    );
+
+                LMI_ASSERT(ui.Select(column_name));
+
+                DoUpdateDialogUI(dialog);
+                }
+
+            // Finally return to the initial checkbox.
+            for(std::size_t n = 0; n < number_of_custom_columns; ++n)
+                {
+                ui.Char(WXK_TAB, wxMOD_SHIFT);
+                }
+
+            wxYield();
+
+            // And set it to the desired value.
+            ui.Char(use_builtin_summary_ ? '+' : '-');
+            wxYield();
+            }
+
+      private:
+        bool const use_builtin_summary_;
+    };
+
+    wxTEST_DIALOG
+        (wxYield()
+        ,ChangeCalculationSummaryInPreferencesDialog(b)
+        );
+}
+
+void check_calculation_summary_columns
+    (std::size_t number_of_columns
+    ,name_and_title const columns_info[]
+    )
+{
+    // Create a new illustration.
+    wx_test_new_illustration ill;
+
+    // Find the window displaying HTML contents of the illustration view.
+    wxWindow* const focus = wxWindow::FindFocus();
+    LMI_ASSERT(focus);
+
+    wxHtmlWindow* const htmlwin = dynamic_cast<wxHtmlWindow*>(focus);
+    LMI_ASSERT(htmlwin);
+
+    // And get the HTML from it.
+    wxHtmlParser* const parser = htmlwin->GetParser();
+    LMI_ASSERT(parser);
+    LMI_ASSERT(parser->GetSource());
+
+    wxString const html = *parser->GetSource();
+
+    // We don't need the window any more.
+    ill.close();
+
+    // Find the start of the table after the separating line.
+    size_t pos = html.find("<hr>\n<table");
+    LMI_ASSERT(pos != wxString::npos);
+
+    pos = html.find("\n<td", pos);
+    LMI_ASSERT(pos != wxString::npos);
+
+    pos++;                                          // skip the new line
+
+    // We have found the place where the columns are described in the HTML,
+    // iterate over all of them.
+    for(std::size_t n = 0; n < number_of_columns; ++n)
+        {
+        LMI_ASSERT_EQUAL(wxString(html, pos, 3), "<td");
+
+        pos = html.find(">", pos);                  // end of the <td> tag
+        LMI_ASSERT(pos != wxString::npos);
+
+        pos++;                                      // <td> tag contents
+
+        size_t const next = html.find("\n", pos);   // the next line start
+        LMI_ASSERT(next != wxString::npos);
+
+        // Extract the column title from the rest of the line.
+        wxString title;
+        LMI_ASSERT(wxString(html, pos, next - pos).EndsWith(" </td>", &title));
+
+        LMI_ASSERT_EQUAL(title, columns_info[n].title);
+
+        pos = next + 1;
+        }
+
+    LMI_ASSERT_EQUAL(wxString(html, pos, 5), "</tr>");
+}
+
+// Save the current clipboard contents to a file with the given name,
+// overwriting it if necessary.
+void save_clipboard(wxString const& filename)
+{
+    wxFFile f(filename, "w");
+    LMI_ASSERT(f.IsOpened());
+    LMI_ASSERT(f.Write(wxString(ClipboardEx::GetText())));
+    LMI_ASSERT(f.Close());
+}
+
+// Save the illustration calculation summary and full data to files with the
+// given prefix.
+void save_illustration_data(wxString const& prefix)
+{
+    wxUIActionSimulator ui;
+    ui.Char('c', wxMOD_CONTROL); // "Illustration|Copy calculation summary"
+    wxYield();
+    save_clipboard(prefix + "IllSummary.txt");
+
+    ui.Char('d', wxMOD_CONTROL); // "Illustration|Copy full illustration data"
+    wxYield();
+    save_clipboard(prefix + "IllFull.txt");
+}
+
+} // Unnamed namespace.
+
+LMI_WX_TEST_CASE(calculation_summary)
+{
+    configurable_settings const& settings = configurable_settings::instance();
+
+    use_builtin_calculation_summary(true);
+
+    LMI_ASSERT(settings.calculation_summary_columns().empty());
+    LMI_ASSERT(settings.use_builtin_calculation_summary());
+
+    check_calculation_summary_columns
+        (number_of_default_columns
+        ,default_columns_info
+        );
+
+    use_builtin_calculation_summary(false);
+
+    // Concatenate all the custom column names together. Notice that the
+    // trailing space is intentional as it is present in the configurable
+    // settings file too.
+    std::string all_custom_columns;
+    for(std::size_t n = 0; n < number_of_custom_columns; ++n)
+        {
+        all_custom_columns += custom_columns_info[n].name;
+        all_custom_columns += ' ';
+        }
+
+    LMI_ASSERT_EQUAL(settings.calculation_summary_columns(), 
all_custom_columns);
+    LMI_ASSERT(!settings.use_builtin_calculation_summary());
+
+    check_calculation_summary_columns
+        (number_of_custom_columns
+        ,custom_columns_info
+        );
+
+    wxUIActionSimulator ui;
+
+    wx_test_new_illustration ill;
+    save_illustration_data("New");
+    ill.close();
+
+    wx_test_new_census census;
+    ui.Char('r', wxMOD_CONTROL | wxMOD_SHIFT); // "Census|Run case"
+    wxYield();
+
+    save_illustration_data("Calc");
+
+    // Close the illustration opened by "Run case".
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxYield();
+
+    census.close();
+}


Property changes on: lmi/trunk/wx_test_calculation_summary.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_case.hpp
===================================================================
--- lmi/trunk/wx_test_case.hpp                          (rev 0)
+++ lmi/trunk/wx_test_case.hpp  2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,88 @@
+// Supporting framework for wx interface test cases.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifndef wx_test_case_hpp
+#define wx_test_case_hpp
+
+#include "config.hpp"
+
+#include "uncopyable_lmi.hpp"
+
+class wxConfigBase;
+
+/// Base class for the test case objects.
+///
+/// It is only supposed to be used by LMI_WX_TEST_CASE macro and not directly.
+class wx_base_test_case
+    :private lmi::uncopyable<wx_base_test_case>
+{
+  public:
+    /// The function actually executing the test code.
+    ///
+    /// This function should throw an exception to signal any failures.
+    virtual void run() = 0;
+
+    char const* get_name() const { return m_name; }
+
+    // Only required to fix g++ warning about a class having virtual functions
+    // but a non-virtual dtor, as this class is not used polymorphically the
+    // dtor doesn't really need to be virtual.
+    virtual ~wx_base_test_case() { }
+
+  protected:
+    /// The argument must be a literal, as we just store the pointer.
+    explicit wx_base_test_case(char const* name);
+
+    /// Get the object containing test configuration.
+    ///
+    /// The returned object will have the group containing the options for this
+    /// test as its current path for convenience.
+    wxConfigBase const& config() const;
+
+    char const* const m_name;
+};
+
+/// Define a test function and register it with the application tester.
+///
+/// Usage is:
+///
+///     LMI_WX_TEST_CASE(my_test)
+///     {
+///         ... code of the test ...
+///     }
+#define LMI_WX_TEST_CASE(name) \
+class wx_test_case_##name \
+    :public wx_base_test_case \
+{ \
+  public: \
+    wx_test_case_##name() \
+        :wx_base_test_case(#name) \
+        { \
+        } \
+ \
+    virtual void run(); \
+}; \
+static wx_test_case_##name wx_test_case_##name##_instance; \
+void wx_test_case_##name::run()
+
+#endif // wx_test_case_hpp


Property changes on: lmi/trunk/wx_test_case.hpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_config_settings.cpp
===================================================================
--- lmi/trunk/wx_test_config_settings.cpp                               (rev 0)
+++ lmi/trunk/wx_test_config_settings.cpp       2014-10-25 14:42:26 UTC (rev 
5995)
@@ -0,0 +1,68 @@
+// Configurable settings test case for the GUI test suite.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "wx_test_case.hpp"
+
+#include <boost/filesystem/operations.hpp>
+
+LMI_WX_TEST_CASE(configurable_settings)
+{
+    LMI_ASSERT(fs::exists("/etc/opt/lmi/configurable_settings.xml"));
+
+    configurable_settings const& settings = configurable_settings::instance();
+    LMI_ASSERT_EQUAL(settings.libraries_to_preload(), "");
+    LMI_ASSERT_EQUAL(settings.xsl_fo_command(), "CMD /c c:/fop-0.20.5/fop");
+
+    std::string skin = settings.skin_filename();
+    std::string default_input = settings.default_input_filename();
+    LMI_ASSERT_WITH_MSG
+        (  "skin_coli_boli.xrc" == skin
+        || "skin_group_carveout.xrc" == skin
+        || "skin_group_carveout2.xrc" == skin
+        || "reg_d.xrc" == skin
+        ,"unknown skin " << skin
+        );
+    if ("skin_coli_boli.xrc" == skin)
+        {
+        LMI_ASSERT_EQUAL(default_input, "c:/fop-0.20.5/coli_boli_default.ill");
+        }
+    if ("skin_group_carveout.xrc" == skin)
+        {
+        LMI_ASSERT_EQUAL(default_input, 
"c:/fop-0.20.5/group_carveout_default.ill");
+        }
+    if ("skin_group_carveout2.xrc" == skin)
+        {
+        LMI_ASSERT_EQUAL(default_input, 
"c:/fop-0.20.5/group_carveout_default.ill");
+        }
+    if ("reg_d.xrc" == skin)
+        {
+        LMI_ASSERT_EQUAL(default_input, 
"c:/fop-0.20.5/private_placement_default.ill");
+        }
+}


Property changes on: lmi/trunk/wx_test_config_settings.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_create_open.cpp
===================================================================
--- lmi/trunk/wx_test_create_open.cpp                           (rev 0)
+++ lmi/trunk/wx_test_create_open.cpp   2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,144 @@
+// Test case for creating new files of all types and opening them.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "mvc_controller.hpp"
+#include "wx_test_case.hpp"
+#include "version.hpp"
+
+#include <wx/dialog.h>
+#include <wx/scopeguard.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+// Helper of test_new_file_and_save() which tests creating a new file of
+// the type corresponding to the key argument, used to select this type in
+// the "New" popup menu.
+//
+// The last argument indicates whether a dialog is shown when creating a
+// new file of this type (e.g. true for illustrations, false for census).
+// It affects this function behaviour in two ways: first, it needs to be
+// ready for this dialog appearing and, second, "File|Save" menu command is
+// disabled for the files created in this way and "File|Save as" needs to
+// be used instead.
+void do_test_create_open(int key, wxString const& file, bool uses_dialog)
+{
+    LMI_ASSERT(!wxFileExists(file));
+
+    wxUIActionSimulator z;
+    z.Char('n', wxMOD_CONTROL); // new file
+    z.Char(key               ); // choose document type
+    if (uses_dialog)
+        {
+        wxTEST_DIALOG
+            (wxYield()
+            ,wxExpectDismissableModal<MvcController>(wxID_OK)
+            );
+        }
+    wxYield();
+
+    z.Char(uses_dialog ? 'a' : 's', wxMOD_CONTROL); // save or save as
+    wxTEST_DIALOG
+        (wxYield()
+        ,wxExpectModal<wxFileDialog>(file)
+        );
+    wxYield();
+
+    LMI_ASSERT(wxFileExists(file));
+    wxON_BLOCK_EXIT1(wxRemoveFile, file);
+
+    z.Char('l', wxMOD_CONTROL); // close document
+    wxYield();
+
+    z.Char('o', wxMOD_CONTROL); // and open it again
+
+    if (uses_dialog)
+        {
+        wxTEST_DIALOG
+            (wxYield()
+            ,wxExpectModal<wxFileDialog>(file)
+            ,wxExpectDismissableModal<MvcController>(wxID_OK)
+            );
+        }
+    else
+        {
+        wxTEST_DIALOG
+            (wxYield()
+            ,wxExpectModal<wxFileDialog>(file)
+            );
+        }
+    wxYield();
+
+    z.Char('l', wxMOD_CONTROL); // close it finally
+    wxYield();
+}
+
+LMI_WX_TEST_CASE(create_open_census)
+{
+    do_test_create_open('c', "testfile.cns",  false);
+}
+
+LMI_WX_TEST_CASE(create_open_illustration)
+{
+    do_test_create_open('i', "testfile.ill",  true);
+}
+
+LMI_WX_TEST_CASE(create_open_database)
+{
+    do_test_create_open('d', "testfile.database", false);
+}
+
+LMI_WX_TEST_CASE(create_open_policy)
+{
+    do_test_create_open('p', "testfile.policy",  false);
+}
+
+LMI_WX_TEST_CASE(create_open_rounding)
+{
+    do_test_create_open('r', "testfile.rounding", false);
+}
+
+LMI_WX_TEST_CASE(create_open_strata)
+{
+    do_test_create_open('s', "testfile.strata", false);
+}
+
+LMI_WX_TEST_CASE(create_open_mec)
+{
+    do_test_create_open('m', "testfile.mec", true);
+}
+
+LMI_WX_TEST_CASE(create_open_gpt)
+{
+    do_test_create_open('g', "testfile.gpt", true);
+}
+
+LMI_WX_TEST_CASE(create_open_text)
+{
+    do_test_create_open('x', "testfile.txt", false);
+}


Property changes on: lmi/trunk/wx_test_create_open.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_default_input.cpp
===================================================================
--- lmi/trunk/wx_test_default_input.cpp                         (rev 0)
+++ lmi/trunk/wx_test_default_input.cpp 2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,49 @@
+// Default input test case for the GUI test suite.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "calendar_date.hpp"
+#include "illustrator.hpp"
+#include "input.hpp"
+#include "wx_test_case.hpp"
+
+#include <wx/log.h>
+
+LMI_WX_TEST_CASE(default_input)
+{
+    calendar_date const today;
+    calendar_date const first_of_month(today.year(), today.month(), 1);
+
+    Input const& cell = default_cell();
+    calendar_date const effective_date = 
exact_cast<tnr_date>(cell["EffectiveDate"])->value();
+    LMI_ASSERT_EQUAL(effective_date, first_of_month);
+
+    std::string const general_account_date = 
exact_cast<numeric_sequence>(cell["GeneralAccountRate"])->value();
+    LMI_ASSERT(!general_account_date.empty());
+    wxLogMessage("GeneralAccountRate is \"%s\"", general_account_date.c_str());
+}


Property changes on: lmi/trunk/wx_test_default_input.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_default_update.cpp
===================================================================
--- lmi/trunk/wx_test_default_update.cpp                                (rev 0)
+++ lmi/trunk/wx_test_default_update.cpp        2014-10-25 14:42:26 UTC (rev 
5995)
@@ -0,0 +1,97 @@
+// Check that the default file can be opened and modified.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "wx_test_case.hpp"
+#include "wx_test_mvc_dialog.hpp"
+#include "wx_test_statusbar.hpp"
+
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+#include <boost/filesystem/operations.hpp>
+
+LMI_WX_TEST_CASE(default_update)
+{
+    wxUIActionSimulator ui;
+
+    // Change the "MEC Avoidance" option in the first page of the defaults
+    // dialog.
+    ui.Char('t', wxMOD_CONTROL); // "File|Default"
+
+    struct change_mac_in_defaults_dialog
+        :public ExpectMvcDialog
+    {
+        virtual void DoRunDialog(MvcController* dialog) const
+            {
+            wxUIActionSimulator ui;
+
+            // Go to the first page: as the dialog remembers its last opened
+            // page, it might not open on it.
+            ui.Char(WXK_HOME);
+            wxYield();
+
+            // Select the first button of the "MEC Avoidance" radio box.
+            ui.Char(WXK_TAB);
+            ui.Char(WXK_TAB);
+            wxYield();
+
+            // Change its value: it doesn't matter which button is selected,
+            // pressing the down arrow will always toggle the selection in a
+            // radio box with two buttons.
+            ui.Char(WXK_DOWN);
+            wxYield();
+            }
+    };
+
+    wxTEST_DIALOG
+        (wxYield()
+        ,change_mac_in_defaults_dialog()
+        );
+
+    // Save the default document.
+    ui.Char('s', wxMOD_CONTROL); // "File|Save"
+    wxYield();
+
+    // Verify that the expected message about saving it was given.
+    std::string const
+        filename = configurable_settings::instance().default_input_filename();
+
+    LMI_ASSERT_EQUAL
+        (get_main_window_statusbar_text()
+        ,wxString::Format("Saved '%s'.", filename)
+        );
+
+    // Close the document now that it's not needed any more.
+    ui.Char('l', wxMOD_CONTROL); // "File|Close"
+    wxYield();
+
+    // Finally also check that the file actually exists.
+    LMI_ASSERT(fs::exists(filename));
+}


Property changes on: lmi/trunk/wx_test_default_update.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_expiry_dates.cpp
===================================================================
--- lmi/trunk/wx_test_expiry_dates.cpp                          (rev 0)
+++ lmi/trunk/wx_test_expiry_dates.cpp  2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,78 @@
+// Expire dates test case for the GUI test suite.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "calendar_date.hpp"
+#include "global_settings.hpp"
+#include "wx_test_case.hpp"
+#include "version.hpp"
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/filesystem/operations.hpp>
+
+LMI_WX_TEST_CASE(expiry_dates)
+{
+    fs::path expiry_path(global_settings::instance().data_directory() / 
"expiry");
+    fs::ifstream is(expiry_path);
+    LMI_ASSERT(is);
+
+    calendar_date begin(last_yyyy_date ());
+    calendar_date end  (gregorian_epoch());
+    is >> begin >> end;
+    LMI_ASSERT(is);
+    LMI_ASSERT(is.eof());
+
+    // The begin date must either be the first of month itself or a date in the
+    // previous month, in which case we're interested in the end of the
+    // following month and not the same one.
+    int year = begin.year();
+    int month = begin.month();
+    int days_in_month;
+
+    if(begin.day() == 1)
+        {
+        days_in_month = begin.days_in_month();
+        }
+    else
+        {
+        if(month == 12)
+            {
+            month = 1;
+            year++;
+            }
+        else
+            {
+            month++;
+            }
+
+        days_in_month = calendar_date(year, month, 1).days_in_month();
+        }
+
+    calendar_date const end_of_month(year, month, days_in_month);
+    LMI_ASSERT_EQUAL(end, end_of_month);
+}


Property changes on: lmi/trunk/wx_test_expiry_dates.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_extract.cpp
===================================================================
--- lmi/trunk/wx_test_extract.cpp                               (rev 0)
+++ lmi/trunk/wx_test_extract.cpp       2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,74 @@
+// Test extract file formats.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "mvc_controller.hpp"
+#include "wx_test_case.hpp"
+
+#include <wx/filename.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+#include <stdexcept>
+
+LMI_WX_TEST_CASE(extract)
+{
+    wxUIActionSimulator ui;
+    ui.Char('o', wxMOD_CONTROL);    // "File|Open"
+
+    wxFileName fn(configurable_settings::instance().default_input_filename());
+    fn.SetFullName("ExtractV6.ill");
+    wxTEST_DIALOG
+        (wxYield()
+         ,wxExpectModal<wxFileDialog>(fn.GetFullPath())
+         ,wxExpectModal<wxMessageDialog>(wxOK)  // Dismiss first warning.
+         ,wxExpectModal<wxMessageDialog>(wxOK)  // And the second one.
+         ,wxExpectDismissableModal<MvcController>(wxID_OK)  // Accept defaults.
+        );
+
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxTEST_DIALOG
+        (wxYield()
+        ,wxExpectModal<wxMessageDialog>(wxNO)   // Don't save changes.
+        );
+
+    ui.Char('o', wxMOD_CONTROL);    // "File|Open"
+
+    fn.SetFullName("ExtractV5.cns");
+    wxTEST_DIALOG
+        (wxYield()
+         ,wxExpectModal<wxFileDialog>(fn.GetFullPath())
+         ,wxExpectModal<wxMessageDialog>(wxOK)  // Dismiss first warning.
+         ,wxExpectModal<wxMessageDialog>(wxOK)  // And the second one.
+         ,wxExpectModal<wxMessageDialog>(wxOK)  // And the third one.
+        );
+
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxYield();
+}


Property changes on: lmi/trunk/wx_test_extract.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_input_sequences.cpp
===================================================================
--- lmi/trunk/wx_test_input_sequences.cpp                               (rev 0)
+++ lmi/trunk/wx_test_input_sequences.cpp       2014-10-25 14:42:26 UTC (rev 
5995)
@@ -0,0 +1,62 @@
+// Test running the input sequences case.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "wx_test_case.hpp"
+
+#include <wx/filename.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+LMI_WX_TEST_CASE(input_sequences)
+{
+    // Construct the path of the file to open, it's supposed to be in the same
+    // directory as the default input filename.
+    wxFileName fn(configurable_settings::instance().default_input_filename());
+    fn.SetFullName("InputSequences.cns");
+
+    wxUIActionSimulator ui;
+
+    ui.Char('o', wxMOD_CONTROL);    // "File|Open"
+    wxTEST_DIALOG
+        (wxYield()
+        ,wxExpectModal<wxFileDialog>(fn.GetFullPath())
+        );
+
+    ui.Char('r', wxMOD_CONTROL | wxMOD_SHIFT); // "Census|Run case"
+    wxYield();
+
+    // Close the illustration opened by "Run case".
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxYield();
+
+    // And the census itself as well.
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxYield();
+}


Property changes on: lmi/trunk/wx_test_input_sequences.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_input_validation.cpp
===================================================================
--- lmi/trunk/wx_test_input_validation.cpp                              (rev 0)
+++ lmi/trunk/wx_test_input_validation.cpp      2014-10-25 14:42:26 UTC (rev 
5995)
@@ -0,0 +1,82 @@
+// Test validation of input ranges in a census.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "wx_test_case.hpp"
+
+#include <wx/filename.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+#include <stdexcept>
+
+LMI_WX_TEST_CASE(input_validation)
+{
+    wxUIActionSimulator ui;
+    ui.Char('o', wxMOD_CONTROL);    // "File|Open"
+
+    wxFileName fn(configurable_settings::instance().default_input_filename());
+    fn.SetFullName("CoiMultiplier.cns");
+    wxTEST_DIALOG
+        (wxYield()
+         ,wxExpectModal<wxFileDialog>(fn.GetFullPath())
+        );
+
+    ui.Char('r', wxMOD_CONTROL | wxMOD_SHIFT);  // "Census|Run case"
+
+    // Test that the expected exception is generated.
+    bool error_detected = false;
+    try
+        {
+        wxYield();
+        }
+    catch(std::runtime_error& e)
+        {
+        error_detected = true;
+
+        // The error message contains a line of the form "[file %s, line %d]"
+        // at the end which we want to ignore, as the line number and possibly
+        // the file name can change and are irrelevant to this check anyhow, so
+        // find this line presence and ignore it in comparison.
+        std::string const error_message = e.what();
+        std::string::size_type loc_pos = error_message.find("\n[file");
+        LMI_ASSERT(loc_pos != std::string::npos);
+
+        LMI_ASSERT_EQUAL
+            (error_message.substr(0, loc_pos),
+             "Input validation problems for '':\n"
+             "COI multiplier entered is '0', but it must contain at least one 
number other than zero.\n"
+            );
+        }
+
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxYield();
+
+    LMI_ASSERT(error_detected);
+}


Property changes on: lmi/trunk/wx_test_input_validation.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_mvc_dialog.hpp
===================================================================
--- lmi/trunk/wx_test_mvc_dialog.hpp                            (rev 0)
+++ lmi/trunk/wx_test_mvc_dialog.hpp    2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,82 @@
+// Helper for testing MvcController dialogs.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifndef wx_test_mvc_dialog_hpp
+#define wx_test_mvc_dialog_hpp
+
+#include "config.hpp"
+
+#include "mvc_controller.hpp"
+
+#include <wx/scopeguard.h>
+#include <wx/testing.h>
+
+/// Abstract base class for the concrete expectations defining the actions to
+/// perform when a given MvcController-derived dialog is shown.
+///
+/// The main reason for this class existence is the unusual reliance of
+/// MvcController on wxEVT_UPDATE_UI events for its functionality. As these
+/// events are not sent from inside wxYield(), which is used throughout the
+/// automatic tests, the dialog is not updated (i.e. the controls inside it
+/// are not enabled when they should be, the corresponding program variables
+/// are not updated when GUI controls change, and so on) unless we send these
+/// events ourselves and this class helps with doing it.
+
+class ExpectMvcDialog
+    :public wxExpectModalBase<MvcController>
+{
+  public:
+    virtual int OnInvoked(MvcController* dialog) const
+    {
+        // Bring the dialog up.
+        dialog->Show();
+        wxYield();
+
+        // Perform whichever actions are needed.
+        DoRunDialog(dialog);
+
+        // And ensure that the model data is updated at the end.
+        DoUpdateDialogUI(dialog);
+
+        return wxID_OK;
+    }
+
+  protected:
+    // The method to be implemented in the derived classes for simulating the
+    // user actions that need to be performed in this dialog.
+    //
+    // DoUpdateDialogUI() should be used after simulating any action updating
+    // the state of the dialog.
+    virtual void DoRunDialog(MvcController* dialog) const = 0;
+
+    // Ensure that the dialog state takes into account all the events simulated
+    // so far by explicitly letting it process a wxUpdateUIEvent.
+    void DoUpdateDialogUI(MvcController* dialog) const
+    {
+        wxUpdateUIEvent event(dialog->GetId());
+        event.SetEventObject(dialog);
+        dialog->ProcessWindowEvent(event);
+    }
+};
+
+#endif // wx_test_mvc_dialog_hpp


Property changes on: lmi/trunk/wx_test_mvc_dialog.hpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_new.hpp
===================================================================
--- lmi/trunk/wx_test_new.hpp                           (rev 0)
+++ lmi/trunk/wx_test_new.hpp   2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,166 @@
+// Helper for creating new documents in unattended GUI tests.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifndef wx_test_new_hpp
+#define wx_test_new_hpp
+
+#include "config.hpp"
+
+#include "mvc_controller.hpp"
+#include "uncopyable_lmi.hpp"
+
+#include <wx/log.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+/// Helper base class for classes testing creation of specific new documents.
+///
+/// This class provides methods for closing the current document, optionally
+/// discarding the changes done to it.
+///
+/// Unfortunately it is impossible to close the document automatically from
+/// this class dtor as doing this may result in an exception and throwing from
+/// dtors is too dangerous, generally speaking (and not allowed at all by
+/// default since C++11), to prefer it to an approach involving explicit calls
+/// to close().
+
+class wx_test_new_document_base
+    :private lmi::uncopyable<wx_test_new_document_base>
+{
+  public:
+    wx_test_new_document_base()
+        :opened_(false)
+    {
+    }
+
+    ~wx_test_new_document_base()
+    {
+        // As we don't want to throw an exception from the dtor, all we can do
+        // is to complain to the user directly.
+        if(opened_)
+            {
+            wxSafeShowMessage
+                ("Programming error"
+                ,"A document created during unattended test hasn't been 
closed, "
+                 "please report this."
+                );
+            }
+    }
+
+    // Close the document window, the document must not be modified.
+    void close()
+    {
+        do_close();
+
+        wxYield();
+    }
+
+    // Close the document window, the document must have been modified and the
+    // changes to it will be discarded.
+    void close_discard_changes()
+    {
+        do_close();
+
+        wxTEST_DIALOG(wxYield(), wxExpectModal<wxMessageDialog>(wxNO));
+    }
+
+  protected:
+    // This method should be called by the derived classes when the document
+    // window is really opened.
+    void set_opened() { opened_ = true; }
+
+  private:
+    // Common part of different close() methods.
+    void do_close()
+    {
+        // If we started closing the document, we should reset the flag: even
+        // if closing it fails, we shouldn't complain about forgetting to close
+        // it as we clearly didn't forget to do it.
+        opened_ = false;
+
+        wxUIActionSimulator ui;
+        ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    }
+
+    bool opened_;
+};
+
+/// Represents a new illustration document.
+///
+/// Instantiating an object of this class simulates creating a new 
illustration.
+/// Its close() method must be called before destroying an object of this class
+/// to ensure that it doesn't stay open.
+
+class wx_test_new_illustration
+    :public wx_test_new_document_base
+{
+  public:
+    // Default constructor creates an illustration with the default parameters.
+    wx_test_new_illustration()
+    {
+        do_new_illustration(wxExpectDismissableModal<MvcController>(wxID_OK));
+    }
+
+    // This constructor takes a class responsible for handling the illustration
+    // parameters dialog and may modify it in any desired way before accepting.
+    wx_test_new_illustration(wxModalExpectation const& e)
+    {
+        do_new_illustration(e);
+    }
+
+  private:
+    // Common part of both constructors.
+    void do_new_illustration(wxModalExpectation const& e)
+    {
+        wxUIActionSimulator ui;
+        ui.Char('n', wxMOD_CONTROL);    // "File|New"
+        ui.Char('i');                   // "Illustration"
+
+        wxTEST_DIALOG(wxYield(), e);
+
+        set_opened();
+    }
+};
+
+/// Represents a new census document.
+///
+/// Instantiating an object of this class simulates creating a new census
+/// document. As with illustrations, close() method must be called before
+/// destroying it.
+
+class wx_test_new_census
+    :public wx_test_new_document_base
+{
+  public:
+    wx_test_new_census()
+    {
+        wxUIActionSimulator ui;
+        ui.Char('n', wxMOD_CONTROL);    // "File|New"
+        ui.Char('c');                   // "Census"
+        wxYield();
+
+        set_opened();
+    }
+};
+
+#endif // wx_test_new_hpp


Property changes on: lmi/trunk/wx_test_new.hpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_paste_census.cpp
===================================================================
--- lmi/trunk/wx_test_paste_census.cpp                          (rev 0)
+++ lmi/trunk/wx_test_paste_census.cpp  2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,232 @@
+// Test pasting data into a census.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "data_directory.hpp"
+#include "wx_test_case.hpp"
+#include "wx_test_mvc_dialog.hpp"
+#include "wx_test_new.hpp"
+#include "wx_utility.hpp"
+
+#include <wx/app.h>
+#include <wx/dataview.h>
+#include <wx/dialog.h>
+#include <wx/ffile.h>
+#include <wx/filefn.h>
+#include <wx/html/htmlpars.h>
+#include <wx/mdi.h>
+#include <wx/radiobox.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+namespace
+{
+
+// Helper function to get the census data to be pasted.
+wxString get_census_data()
+{
+    // Get the census example from help. This is an HTML file but we don't have
+    // an HTML parser and HTML is not valid XML, so it can't be parsed as such.
+    // Instead we just rely on the very particular format of this file: right
+    // now it contains the census data between the only occurrences of <pre>
+    // and </pre> tags in it, so locate them and take everything inside.
+
+    wxFFile f(AddDataDir("pasting_to_a_census.html"));
+    LMI_ASSERT(f.IsOpened());
+
+    wxString html;
+    LMI_ASSERT(f.ReadAll(&html));
+
+    size_t const pos_pre = html.find("<pre>\n");
+    LMI_ASSERT(pos_pre != wxString::npos);
+
+    size_t const pos_pre_end = html.find("</pre>", pos_pre);
+    LMI_ASSERT(pos_pre_end != wxString::npos);
+
+    size_t const pos_pre_start = pos_pre + strlen("<pre>\n");
+    wxString const text_pre = html.substr
+                                (pos_pre_start
+                                , pos_pre_end - pos_pre_start
+                                );
+
+    // We're not done yet, we need to deal with the HTML entities. Do use HTML
+    // parsing code in wxWidgets for this at least.
+    return wxHtmlEntitiesParser().Parse(text_pre);
+}
+
+// Helper function to find the wxDataViewCtrl used for the census display.
+//
+// Precondition: the currently active window must be a CensusView.
+wxDataViewCtrl* find_census_list_window()
+{
+    wxWindow* const top_window = wxTheApp->GetTopWindow();
+    LMI_ASSERT(top_window);
+
+    wxMDIParentFrame* const
+        parent_frame = dynamic_cast<wxMDIParentFrame*>(top_window);
+    LMI_ASSERT(parent_frame);
+
+    wxMDIChildFrame* const child_frame = parent_frame->GetActiveChild();
+    LMI_ASSERT(child_frame);
+
+    wxWindowList const& census_children = child_frame->GetChildren();
+    wxWindowList::const_iterator z = census_children.begin();
+    LMI_ASSERT(z != census_children.end());
+
+    wxDataViewCtrl* const dvc = dynamic_cast<wxDataViewCtrl*>(*z);
+    LMI_ASSERT(dvc);
+
+    return dvc;
+}
+
+// Retrieve the list model from list window.
+//
+// Precondition: this wxDataViewCtrl must actually use a list model.
+wxDataViewListModel* get_census_list_model(wxDataViewCtrl* dvc)
+{
+    wxDataViewModel* const model = dvc->GetModel();
+    LMI_ASSERT(model);
+
+    wxDataViewListModel* const
+        list_model = dynamic_cast<wxDataViewListModel*>(model);
+    LMI_ASSERT(list_model);
+
+    return list_model;
+}
+
+// Check for the presence of the column with the given name.
+bool does_list_have_column(wxDataViewCtrl* dvc, wxString const& name)
+{
+    unsigned int const num_columns = dvc->GetColumnCount();
+    for(unsigned int n = 0; n < num_columns; ++n)
+        {
+        if (dvc->GetColumn(n)->GetTitle() == name)
+            {
+            return true;
+            }
+        }
+    return false;
+}
+
+} // Unnamed namespace.
+
+LMI_WX_TEST_CASE(paste_census)
+{
+    // Put the data to paste on clipboard.
+    ClipboardEx::SetText(get_census_data().ToStdString());
+
+    // Create a new census.
+    wx_test_new_census census;
+
+    // Paste data into it.
+    wxUIActionSimulator ui;
+    ui.Char('s', wxMOD_CONTROL | wxMOD_SHIFT); // "Census|Paste census data"
+    wxYield();
+
+    // Find the model containing the cells and check that it was filled in
+    // correctly.
+    wxDataViewCtrl* const list_window = find_census_list_window();
+    wxDataViewListModel* const list_model = get_census_list_model(list_window);
+    LMI_ASSERT_EQUAL(list_model->GetCount(), 7);
+
+    static char const* column_title = "Underwriting Class";
+    LMI_ASSERT(does_list_have_column(list_window, column_title));
+
+    // Change the case defaults to get rid of the underwriting class.
+    ui.Char('e', wxMOD_CONTROL | wxMOD_SHIFT); // "Census|Edit case defaults"
+
+    struct change_class_in_case_defaults_dialog
+        :public ExpectMvcDialog
+    {
+        virtual void DoRunDialog(MvcController* dialog) const
+            {
+            wxUIActionSimulator ui;
+
+            // Go to the third page: as the dialog remembers its last opened
+            // page, ensure that we start from the first one.
+            ui.Char(WXK_HOME);
+            ui.Char(WXK_RIGHT);
+            ui.Char(WXK_RIGHT);
+            wxYield();
+
+            // We can't find directly the radio button we're interested in,
+            // because it's not a real wxWindow, so we need to find the radio
+            // box containing it.
+            wxWindow* const class_window = wxWindow::FindWindowByName
+                ("UnderwritingClass"
+                ,dialog
+                );
+            LMI_ASSERT(class_window);
+
+            wxRadioBox* const
+                class_radiobox = dynamic_cast<wxRadioBox*>(class_window);
+            LMI_ASSERT(class_radiobox);
+
+            // It's difficult to select the radiobox using just
+            // wxUIActionSimulator as there is no keyboard shortcut to navigate
+            // to it and emulating a mouse click on it is tricky as we don't
+            // want to change its selection by clicking on the item, so do it
+            // programmatically, the effect should be absolutely the same.
+            class_radiobox->SetFocus();
+            wxYield();
+
+            ui.Char(WXK_UP); // Select the first, "Preferred", radio button.
+            wxYield();
+
+            LMI_ASSERT_EQUAL(class_radiobox->GetSelection(), 0);
+            }
+    };
+
+    // The menu command above should have opened the "Case defaults" dialog and
+    // our code dealing with it above is supposed to result in an appearance of
+    // "Apply all changes to every cell?" message box for which we provide an
+    // affirmative answer.
+    wxTEST_DIALOG
+        (wxYield()
+        ,change_class_in_case_defaults_dialog()
+        ,wxExpectModal<wxMessageDialog>(wxYES)
+        );
+
+    // Check that we still have the same cells but that now the underwriting
+    // class column has disappeared as its value has been fixed.
+    LMI_ASSERT_EQUAL(list_model->GetCount(), 7);
+    LMI_ASSERT(!does_list_have_column(list_window, column_title));
+
+    // Finally save the census with the pasted data for later inspection.
+    static char const* census_file_name = "PasteCensus.cns";
+
+    ui.Char('a', wxMOD_CONTROL);    // "File|Save as"
+    wxTEST_DIALOG
+        (wxYield()
+        ,wxExpectModal<wxFileDialog>(census_file_name)
+        );
+
+    LMI_ASSERT(wxFileExists(census_file_name));
+
+    census.close();
+}


Property changes on: lmi/trunk/wx_test_paste_census.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_pdf_create.cpp
===================================================================
--- lmi/trunk/wx_test_pdf_create.cpp                            (rev 0)
+++ lmi/trunk/wx_test_pdf_create.cpp    2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,142 @@
+// Test creating PDF output for census and illustration documents.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "wx_test_case.hpp"
+#include "wx_test_new.hpp"
+
+#include <wx/docview.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+#include <boost/filesystem/operations.hpp>
+
+namespace
+{
+
+// Get the name used for the last created document: it depends on the tests
+// that had been ran previously, so get it from the document itself.
+std::string get_current_document_name()
+{
+    wxDocManager const* const docm = wxDocManager::GetDocumentManager();
+    LMI_ASSERT(docm);
+    wxDocument const* const doc = docm->GetCurrentDocument();
+    LMI_ASSERT(doc);
+
+    return doc->GetUserReadableName().ToStdString();
+}
+
+// Build the path for the output PDF with the given base name.
+fs::path make_pdf_path(std::string const& base_name)
+{
+    fs::path pdf_path(configurable_settings::instance().print_directory());
+    pdf_path /= base_name + ".pdf";
+
+    return pdf_path;
+}
+
+// Return the suffix used for the FO files created by printing the census.
+std::string fo_suffix(int n)
+{
+    return wxString::Format(".%09d", n).ToStdString();
+}
+
+} // Unnamed namespace.
+
+LMI_WX_TEST_CASE(pdf_illustration)
+{
+    // Create a new illustration.
+    wx_test_new_illustration ill;
+
+    // Ensure that the output file doesn't exist in the first place.
+    fs::path const pdf_path(make_pdf_path(get_current_document_name()));
+    fs::remove(pdf_path);
+
+    // Launch the PDF creation as side effect of previewing it.
+    wxUIActionSimulator ui;
+    ui.Char('v', wxMOD_CONTROL);    // "File|Print preview"
+    wxYield();
+
+    // Close the illustration, we don't need it any more.
+    ill.close();
+
+    // Finally check for the expected output file existence.
+    LMI_ASSERT(fs::exists(pdf_path));
+
+    // Don't remove it here, the PDF file is still opened in the PDF reader and
+    // can't be removed before it is closed.
+}
+
+LMI_WX_TEST_CASE(pdf_census)
+{
+    // Create a new census.
+    wx_test_new_census census;
+
+    // Add some cells to the census (it starts with one already).
+    wxUIActionSimulator ui;
+    static const int num_cells = 3;
+    for(int n = 0; n < num_cells - 1; ++n)
+        {
+        ui.Char('+', wxMOD_CONTROL);    // "Census|Add cell".
+        wxYield();
+        }
+
+    // Remove the expected output files to avoid false positives if they are
+    // already present and not created by the test.
+    std::string const name = get_current_document_name();
+
+    fs::path const
+        composite_pdf_path(make_pdf_path(name + ".composite" + fo_suffix(0)));
+    fs::remove(composite_pdf_path);
+
+    fs::path cell_pdf_paths[num_cells];
+    for(int n = 0; n < num_cells; ++n)
+        {
+        cell_pdf_paths[n] = make_pdf_path(name + fo_suffix(n + 1));
+        fs::remove(cell_pdf_paths[n]);
+        }
+
+    // Print the census to disk.
+    ui.Char('k', wxMOD_CONTROL | wxMOD_SHIFT);  // "Census|Print case to disk"
+    wxYield();
+
+    // Close the census, we don't need it any more, and answer "No" to the
+    // message box asking whether it should be saved.
+    census.close_discard_changes();
+
+    // Check the existence of the files and, unlike in the illustration case,
+    // also delete them as they are not opened in any external viewer.
+    LMI_ASSERT(fs::exists(composite_pdf_path));
+    fs::remove(composite_pdf_path);
+    for(int n = 0; n < num_cells; ++n)
+        {
+        LMI_ASSERT(fs::exists(cell_pdf_paths[n]));
+        fs::remove(cell_pdf_paths[n]);
+        }
+}


Property changes on: lmi/trunk/wx_test_pdf_create.cpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_statusbar.hpp
===================================================================
--- lmi/trunk/wx_test_statusbar.hpp                             (rev 0)
+++ lmi/trunk/wx_test_statusbar.hpp     2014-10-25 14:42:26 UTC (rev 5995)
@@ -0,0 +1,60 @@
+// Helpers for checking status bar contents in unattended GUI tests.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifndef wx_test_statusbar_hpp
+#define wx_test_statusbar_hpp
+
+#include "config.hpp"
+
+#include "assert_lmi.hpp"
+
+#include <wx/app.h>
+#include <wx/frame.h>
+#include <wx/statusbr.h>
+
+/// Return the status bar of the main window throwing an exception if anything
+/// goes wrong.
+
+inline wxStatusBar const& get_main_window_statusbar()
+{
+    wxWindow* const mainWin = wxTheApp->GetTopWindow();
+    LMI_ASSERT(mainWin);
+
+    wxFrame* const frame = wxDynamicCast(mainWin, wxFrame);
+    LMI_ASSERT(frame);
+
+    wxStatusBar* const status = frame->GetStatusBar();
+    LMI_ASSERT(status);
+
+    return *status;
+}
+
+/// Return the contents of the status of the main window throwing an exception
+/// if it can't be retrieved.
+
+inline wxString get_main_window_statusbar_text()
+{
+    return get_main_window_statusbar().GetStatusText();
+}
+
+#endif // wx_test_statusbar_hpp


Property changes on: lmi/trunk/wx_test_statusbar.hpp
___________________________________________________________________
Added: svn:keywords
   + Id

Added: lmi/trunk/wx_test_validate_output.cpp
===================================================================
--- lmi/trunk/wx_test_validate_output.cpp                               (rev 0)
+++ lmi/trunk/wx_test_validate_output.cpp       2014-10-25 14:42:26 UTC (rev 
5995)
@@ -0,0 +1,193 @@
+// Validate existence and naming conventions of output files.
+//
+// Copyright (C) 2014 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifdef __BORLANDC__
+#   include "pchfile.hpp"
+#   pragma hdrstop
+#endif
+
+#include "assert_lmi.hpp"
+#include "configurable_settings.hpp"
+#include "mvc_controller.hpp"
+#include "uncopyable_lmi.hpp"
+#include "wx_test_case.hpp"
+#include "wx_test_mvc_dialog.hpp"
+#include "wx_test_new.hpp"
+
+#include <wx/filename.h>
+#include <wx/testing.h>
+#include <wx/uiaction.h>
+
+#include <boost/filesystem/operations.hpp>
+
+namespace
+{
+
+/// Class helping to check for the expected output file existence.
+///
+/// This class takes care of ensuring that the file doesn't exist when it is
+/// constructed and provides a way to check for the existence of the file
+/// later. It also cleans up the file when it is destroyed.
+
+class output_file_existence_checker
+    :private lmi::uncopyable<output_file_existence_checker>
+{
+  public:
+    output_file_existence_checker(std::string const& path)
+        :path_(path)
+        {
+        fs::remove(path_);
+        }
+
+    void assert_exists() const
+        {
+        LMI_ASSERT(fs::exists(path_));
+        }
+
+    ~output_file_existence_checker()
+        {
+        try
+            {
+            fs::remove(path_);
+            }
+        catch(...)
+            {
+            }
+        }
+
+  private:
+    fs::path path_;
+};
+
+} // Unnamed namespace.
+
+LMI_WX_TEST_CASE(validate_output_illustration)
+{
+    std::string const&
+        ext = configurable_settings::instance().spreadsheet_file_extension();
+
+    // Build the path existence of which we're going to check and ensure that
+    // it doesn't exist before the start of the test.
+    output_file_existence_checker unnamed_trace("unnamed.monthly_trace" + ext);
+
+    struct enter_comment_in_illustration_dialog
+        :public ExpectMvcDialog
+    {
+        virtual void DoRunDialog(MvcController* dialog) const
+            {
+            wxUIActionSimulator ui;
+
+            // Go to the first page: as the dialog remembers its last opened
+            // page, ensure that we are always on the one we need.
+            ui.Char(WXK_HOME);
+            wxYield();
+
+            // It is difficult to focus the text entry that we're interested
+            // directly from keyboard, so cheat a little and focus it
+            // programmatically.
+            wxWindow* const comments = wxWindow::FindWindowByName
+                ("Comments"
+                ,dialog
+                );
+            LMI_ASSERT(comments);
+
+            comments->SetFocus();
+            wxYield();
+
+            ui.Text("idiosyncrasyZ");
+            wxYield();
+            }
+    };
+
+    // Create a new illustration with the special comment.
+
+    // Double parentheses circumvent the most vexing parse.
+    wx_test_new_illustration ill((enter_comment_in_illustration_dialog()));
+    ill.close_discard_changes();
+
+    // And check that this resulted in the creation of the expected file.
+    unnamed_trace.assert_exists();
+
+    // Open an existing illustration already containing the same comment.
+    wxUIActionSimulator ui;
+
+    output_file_existence_checker
+        existing_trace("MonthlyTrace.monthly_trace" + ext);
+
+    wxFileName fn(configurable_settings::instance().default_input_filename());
+    fn.SetFullName("MonthlyTrace.ill");
+
+    ui.Char('o', wxMOD_CONTROL);    // "File|Open"
+    wxTEST_DIALOG
+        (wxYield()
+        ,wxExpectModal<wxFileDialog>(fn.GetFullPath())
+        ,wxExpectModal<wxMessageDialog>(wxID_OK)          // Ignore warning.
+        ,wxExpectDismissableModal<MvcController>(wxID_OK) // Accept defaults.
+        );
+
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxTEST_DIALOG(wxYield(), wxExpectModal<wxMessageDialog>(wxNO));
+
+    existing_trace.assert_exists();
+}
+
+LMI_WX_TEST_CASE(validate_output_mec)
+{
+    std::string const&
+        ext = configurable_settings::instance().spreadsheet_file_extension();
+
+    // Test creation of the output file when opening a new MEC testing 
document.
+    output_file_existence_checker unnamed_output("unnamed.mec" + ext);
+
+    wxUIActionSimulator ui;
+    ui.Char('n', wxMOD_CONTROL);    // "File|New"
+    ui.Char('m');                   // "MEC testing"
+
+    wxTEST_DIALOG
+        (wxYield()
+        ,wxExpectDismissableModal<MvcController>(wxID_OK)
+        );
+
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxYield();
+
+    unnamed_output.assert_exists();
+
+    // And when opening an existing one.
+    output_file_existence_checker existing_output("MecTesting.mec" + ext);
+
+    wxFileName fn(configurable_settings::instance().default_input_filename());
+    fn.SetFullName("MecTesting.mec");
+
+    ui.Char('o', wxMOD_CONTROL);    // "File|Open"
+    wxTEST_DIALOG
+        (wxYield()
+         ,wxExpectModal<wxFileDialog>(fn.GetFullPath())
+         ,wxExpectDismissableModal<MvcController>(wxID_OK) // Accept defaults.
+        );
+
+    ui.Char('l', wxMOD_CONTROL);    // "File|Close"
+    wxYield();
+
+    existing_output.assert_exists();
+}


Property changes on: lmi/trunk/wx_test_validate_output.cpp
___________________________________________________________________
Added: svn:keywords
   + Id




reply via email to

[Prev in Thread] Current Thread [Next in Thread]