lmi
[Top][All Lists]
Advanced

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

Re: [lmi] Preserving configurable settings after GUI test


From: Greg Chicares
Subject: Re: [lmi] Preserving configurable settings after GUI test
Date: Tue, 10 Jul 2018 22:54:40 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0

On 2018-07-03 00:01, Vadim Zeitlin wrote:
> 
>  There is a long standing TODO item about preserving the contents of
> configurable_settings.xml file after running the GUI unit test, which
> currently modifies it. The problem is that currently there doesn't seem to
> be any simple and reliable way to do it using configurable_settings class
> API: it doesn't allow neither copying it, which could be used to preserve a
> backup copy, nor retrieving the underlying XML file path, which could be
> used to make a backup copy of the file and restore it.
> 
>  I think that the possibility to do either one or the other needs to be
> added, because the only other alternative I see is to use MemberSymbolTable
> class API to make a member-by-member copy, which seems quite ugly. But I
> have a lot of trouble guessing which of the approaches would you prefer.

This isn't an easy question.

> From my point of view, just exposing the XML file path would be the
> simplest way to solve the problem, but it's also the least flexible one,
> i.e. if configurable_settings ever changes to use some other source of
> configurable information than a file (and I think this is perfectly
> possible), the code in the unit test would need to be changed, while just
> allowing to really copy the configurable_settings object contents would
> still continue to work.

Initially I preferred this and wrote the implementation below. But now
I'm not really sure. Is another storage mechanism really feasible?
We can't use wxConfigBase for the command-line lmi binaries, not without
introducing a dependency that we've studiously avoided all these years.
We already use xml extensively, and it seems natural to use it here too.
And our stated goal is that lmi should remain usable forty years after
I retire, i.e., for another fifty or sixty years; I'm confident that
flat files will still work then.

>  So which one of the following would you prefer:
> 
> 1. Make private configuration_filepath() function public, i.e. a (static)
>    member of configurable_settings.
> 2. Make configurable_settings copy ctor and assignment operator public and
>    implement them.

All data members are naturally copyable (no weird stuff like pointers), so
maybe this would be easy. OTOH, the class derives from MemberSymbolTable,
so it's not entirely trivial, but we can just clone
  Input::Input(Input const& z)
  Input& Input::operator=(Input const& z)
so it's not really hard either. But OTTH, this is a Meyers singleton, and
those special member functions are deliberately unimplemented to prevent
anyone from using them by accident; that's a pretty strong reason to keep
them private.

Perhaps a have-our-cake-and-eat-it-too solution is to implement them
privately and extend friendship to its GUI test. Let's call that (2a) for
ease of reference.

> 3. Use MemberSymbolTable methods directly.

That does seem yicky. We'd have to do all the work of (2a) anyway (i.e.,
cloning class Input's special members would be the easiest way), so this
boils down to implementing those special members under deviant names like
  Foo::Copy(Foo const&)
  Foo& Foo::Assign(Foo const&)
which would be unnatural.

> or do you see some other approach?

4. Right now, we have
    void save() const; // public
    void load();       // private
and we could add overloads that take a nondefault filename. That seems
easy enough, especially because the implementations are one-liners.

I'm not sure which of {1, 2a, 4} I like best. What do you think?

Here's my implementation of 1:

---------8<--------8<--------8<--------8<--------8<--------8<--------8<-------
diff --git a/configurable_settings.cpp b/configurable_settings.cpp
index 7aa56a00..9ea4186e 100644
--- a/configurable_settings.cpp
+++ b/configurable_settings.cpp
@@ -46,11 +46,17 @@ template class xml_serializable<configurable_settings>;
 
 namespace
 {
-std::string const& configuration_filename()
+std::string const& default_calculation_summary_columns()
 {
-    static std::string s("configurable_settings.xml");
+    static std::string s
+        ("Outlay"
+        " AcctVal_Current"
+        " CSVNet_Current"
+        " EOYDeathBft_Current"
+        );
     return s;
 }
+} // Unnamed namespace.
 
 /// Store the complete configuration-file path at startup, in case
 /// it's non-complete--as is typical msw usage.
@@ -79,23 +85,25 @@ std::string const& configuration_filename()
 /// most appropriate. (A knowledgeable user could of course move it
 /// aside if it is desired to use the file on the read-only medium.)
 
-fs::path const& configuration_filepath()
+std::string const& configuration_filepath()
 {
-    static fs::path complete_path;
+    static std::string complete_path;
     if(!complete_path.empty())
         {
         return complete_path;
         }
 
-    std::string filename = "/etc/opt/lmi/" + configuration_filename();
+    static std::string const basename {"configurable_settings.xml"};
+
+    std::string filename = "/etc/opt/lmi/" + basename;
     if(0 != access(filename.c_str(), R_OK))
         {
-        filename = AddDataDir(configuration_filename());
+        filename = AddDataDir(basename);
         if(0 != access(filename.c_str(), R_OK))
             {
             alarum()
                 << "No readable file '"
-                << configuration_filename()
+                << basename
                 << "' exists."
                 << LMI_FLUSH
                 ;
@@ -114,22 +122,10 @@ fs::path const& configuration_filepath()
         }
 
     validate_filepath(filename, "Configurable-settings file");
-    complete_path = fs::system_complete(filename);
+    complete_path = fs::system_complete(filename).string();
     return complete_path;
 }
 
-std::string const& default_calculation_summary_columns()
-{
-    static std::string s
-        ("Outlay"
-        " AcctVal_Current"
-        " CSVNet_Current"
-        " EOYDeathBft_Current"
-        );
-    return s;
-}
-} // Unnamed namespace.
-
 configurable_settings::configurable_settings()
     :calculation_summary_columns_        
(default_calculation_summary_columns())
     ,census_paste_palimpsestically_      (true                                 
)
diff --git a/configurable_settings.hpp b/configurable_settings.hpp
index b1cbeade..c5c19b99 100644
--- a/configurable_settings.hpp
+++ b/configurable_settings.hpp
@@ -112,6 +112,8 @@ class LMI_SO configurable_settings final
     std::string xsl_fo_command_;
 };
 
+std::string const& LMI_SO configuration_filepath();
+
 std::vector<std::string>        input_calculation_summary_columns();
 // This function must be visible to 'wx_test_calculation_summary.cpp'.
 std::vector<std::string> LMI_SO effective_calculation_summary_columns();
--------->8-------->8-------->8-------->8-------->8-------->8-------->8-------



reply via email to

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