test/src/EngineTestSuite.cc
author Krista 'DarthMama' Bennett <krista@pep.foundation>
Mon, 28 Jan 2019 14:04:12 +0100
changeset 3246 ec48ea509c8d
parent 3229 6d555032f84c
child 3270 d8aea79654c3
child 3277 fe1e94372261
permissions -rw-r--r--
Added dir creation and script for gpg socket dir to default
     1 #include <stdlib.h>
     2 #include <sys/stat.h>
     3 #include <errno.h>
     4 #include <stdlib.h>
     5 #include <unistd.h>
     6 #include <ftw.h>
     7 #include <assert.h>
     8 #include <fstream>
     9 #include <iostream>
    10 #include <sys/types.h>
    11 #include <sys/stat.h>
    12 
    13 #include <string>
    14 #include <vector>
    15 #include <utility>
    16 
    17 #include "platform_unix.h"
    18 
    19 #include "test_util.h"
    20 #include "EngineTestSuite.h"
    21 #include "pEpTestStatic.h"
    22 #include <algorithm>
    23 
    24 using namespace std;
    25 
    26 // Constructor
    27 EngineTestSuite::EngineTestSuite(string suitename, string test_home_dir) {
    28     // FIXME: deal with base
    29     test_home = test_home_dir;
    30             
    31     number_of_tests = 0;
    32     on_test_number = 0;
    33     real_home = getenv("HOME");
    34 }
    35 
    36 EngineTestSuite::~EngineTestSuite() {}
    37 
    38 void EngineTestSuite::add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()> test_func) {
    39     test_map.insert(test_func);
    40     register_test(test_func.second, test_func.first);
    41     number_of_tests++;
    42 }
    43 
    44 void EngineTestSuite::copy_conf_file_to_test_dir(const char* dest_path, const char* conf_orig_path, const char* conf_dest_name) {
    45     string conf_dest_path = dest_path;
    46     
    47     struct stat pathinfo;
    48 
    49     if(stat(conf_dest_path.c_str(), &pathinfo) != 0) {
    50         int errchk = mkdir(conf_dest_path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    51         if (errchk != 0)
    52             throw std::runtime_error("Error accessing conf file directory.");
    53     }
    54     
    55     conf_dest_path += "/";
    56     conf_dest_path += conf_dest_name;
    57     
    58     ifstream src(conf_orig_path);
    59     ofstream dst(conf_dest_path.c_str(), ios::trunc);
    60     
    61     assert(src);
    62     assert(dst);
    63     
    64     dst << src.rdbuf();
    65      
    66     src.close();
    67     dst.close();
    68 }
    69 
    70 void EngineTestSuite::add_file_to_gpg_dir_queue(string copy_from, string dst_fname) {    
    71     gpgdir_fileadd_queue.push_back(make_pair(copy_from, dst_fname));
    72 }
    73 
    74 void EngineTestSuite::add_file_to_home_dir_queue(string copy_from, string dst_fname) {
    75     homedir_fileadd_queue.push_back(make_pair(copy_from, dst_fname));
    76 }
    77 
    78 void EngineTestSuite::process_file_queue(string dirname, vector<pair<string, string>> file_queue) {
    79     if (file_queue.empty())
    80         return;
    81         
    82     vector<pair<string, string>>::iterator it;
    83     
    84     for (it = file_queue.begin(); it != file_queue.end(); it++) {
    85         copy_conf_file_to_test_dir(dirname.c_str(), it->first.c_str(), it->second.c_str());
    86     }
    87     
    88     file_queue.clear();
    89 }
    90 
    91 void EngineTestSuite::set_full_env() {
    92     set_full_env(NULL, NULL, NULL);
    93 }
    94 
    95 void EngineTestSuite::set_full_env(const char* gpg_conf_copy_path, const char* gpg_agent_conf_file_copy_path, const char* db_conf_file_copy_path) {
    96     int success = 0;
    97     struct stat dirchk;
    98     
    99     set_my_name();
   100 
   101 // FIXME
   102 #ifndef USE_NETPGP
   103     success = system("gpgconf --kill all");
   104     if (success != 0)
   105         throw std::runtime_error("SETUP: Error when executing 'gpgconf --kill all'.");    
   106 #endif
   107 
   108     if (stat(test_home.c_str(), &dirchk) == 0) {
   109         if (!S_ISDIR(dirchk.st_mode))
   110             throw std::runtime_error(("The test directory, " + test_home + "exists, but is not a directory.").c_str()); 
   111                     
   112         struct stat buf;
   113 
   114         if (stat(test_home.c_str(), &buf) == 0) {
   115             int success = nftw((test_home + "/.").c_str(), util_delete_filepath, 100, FTW_DEPTH);
   116         }
   117     }
   118     else {
   119         int errchk = mkdir(test_home.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
   120         cout << errchk << endl;
   121         if (errchk != 0)
   122             throw std::runtime_error("Error creating a test directory.");
   123     }
   124 
   125     if (my_name.size() > pEpTestStatic::classname_chars)
   126         my_name.resize(pEpTestStatic::classname_chars);
   127 
   128     if (on_test_number > pEpTestStatic::max_test_num) {
   129         cerr << "Warning - there are at least " << pEpTestStatic::max_test_num << " tests in this suite. While this probably won't cause "
   130              << endl << "problems, there is an obscure possibility that if your test path is REALLY REALLY LONG, tests will fail because gpg-agent "
   131              << endl << "won't start with huge paths. In general, however, we stop well before these limits, and pEpTestStatic::testnum_path_chars "
   132              << endl << "is overly conservative, so you probably don't need to worry." << endl;
   133     }    
   134 
   135     temp_test_home = test_home + "/" + my_name;
   136     
   137     int errchk = mkdir(temp_test_home.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
   138     if (errchk != 0)
   139         throw std::runtime_error("Error creating a test directory.");
   140 
   141     temp_test_home += "/" + to_string(on_test_number);
   142 
   143     errchk = mkdir(temp_test_home.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
   144     if (errchk != 0)
   145         throw std::runtime_error("Error creating a test directory.");
   146 
   147     // TODO: This is *nix specific, which the current testing env is anyway,
   148     // but it needn't remain so forever and always
   149 
   150     string home = getenv("HOME");
   151 
   152     char* tmp = NULL;
   153     
   154     tmp = getenv("GNUPGHOME");
   155 
   156     prev_pgp_home.clear();
   157     
   158     if (tmp)
   159         prev_pgp_home = tmp;
   160         
   161     if (temp_test_home.empty())
   162         throw std::runtime_error("SETUP: BAD INITIALISATION. No test home.");
   163     
   164     assert(temp_test_home.compare(home) != 0);
   165     assert(temp_test_home.compare(home + "/") != 0);
   166     assert(temp_test_home.compare(home + "/.gnupg") != 0); // This is an EXCLUSION test, so we leave this.
   167     assert(temp_test_home.compare(home + ".gnupg") != 0);
   168     assert(temp_test_home.compare(home + "/gnupg") != 0);
   169     assert(temp_test_home.compare(home + "gnupg") != 0);
   170     assert(temp_test_home.compare(prev_pgp_home) != 0);
   171     assert(temp_test_home.compare(prev_pgp_home + "/gnupg") != 0);
   172     assert(temp_test_home.compare(prev_pgp_home + "gnupg") != 0);
   173     assert(temp_test_home.compare(prev_pgp_home + "/.gnupg") != 0);
   174     assert(temp_test_home.compare(prev_pgp_home + ".gnupg") != 0);
   175 
   176     if (temp_test_home.compare(home) == 0 || temp_test_home.compare(home + "/") == 0 ||
   177         temp_test_home.compare(home + "/gnupg") == 0 || temp_test_home.compare(home + "gnupg") == 0 ||
   178         temp_test_home.compare(home + "/.gnupg") == 0 || temp_test_home.compare(home + ".gnupg") == 0 ||
   179         temp_test_home.compare(prev_pgp_home) == 0 || temp_test_home.compare(prev_pgp_home + "/gnupg") == 0 ||
   180         temp_test_home.compare(prev_pgp_home + "gnupg") == 0 || temp_test_home.compare(prev_pgp_home + "/.gnupg") == 0 ||
   181         temp_test_home.compare(prev_pgp_home + ".gnupg") == 0)
   182         throw std::runtime_error("SETUP: new pgp homedir threatens to mess up user pgp homedir (and delete all their keys). NO DICE.");
   183     
   184 //    cout << "Ok - checked if new test home will be safe. We'll try and make the directory, deleting it if it has already exists." << endl;
   185     cout << "Test home directory is " << temp_test_home << endl;
   186     
   187     struct stat buf;
   188     
   189     success = setenv("GNUPGHOME", (temp_test_home + "/gnupg").c_str(), 1);
   190     if (success != 0)
   191         throw std::runtime_error("SETUP: Error when setting GNUPGHOME.");
   192 
   193     cout << "New GNUPGHOME is " << getenv("GNUPGHOME") << endl << endl;
   194     
   195     success = setenv("HOME", temp_test_home.c_str(), 1);
   196     if (success != 0)
   197         throw std::runtime_error("SETUP: Cannot set test_home for init.");
   198 
   199     string tmp_gpg_dir = temp_test_home + "/.gnupg";
   200 
   201     process_file_queue(tmp_gpg_dir, gpgdir_fileadd_queue);
   202     process_file_queue(temp_test_home, homedir_fileadd_queue);
   203 
   204     if (gpg_conf_copy_path)
   205         copy_conf_file_to_test_dir((temp_test_home + "/gnupg").c_str(), gpg_conf_copy_path, "gpg.conf");
   206     if (gpg_agent_conf_file_copy_path)        
   207         copy_conf_file_to_test_dir((temp_test_home + "/gnupg").c_str(), gpg_agent_conf_file_copy_path, "gpg-agent.conf");
   208     if (db_conf_file_copy_path)
   209         copy_conf_file_to_test_dir(temp_test_home.c_str(), db_conf_file_copy_path, ".pEp_management.db");
   210         
   211     unix_local_db(true);
   212     gpg_conf(true);
   213     gpg_agent_conf(true);
   214     
   215 //    cout << "calling init()\n";
   216     PEP_STATUS status = init(&session);
   217 #ifndef USE_NETPGP            
   218     success = system("gpgconf --create-socketdir");
   219     if (success != 0)
   220         throw std::runtime_error("RESTORE: Error when executing 'gpgconf --create-socketdir'.");            
   221     system("gpg-connect-agent /bye");   // Just in case - otherwise, we die on MacOS sometimes. Is this enough??
   222 #endif 
   223     assert(status == PEP_STATUS_OK);
   224     assert(session);
   225 //    cout << "init() completed.\n";
   226 
   227 }
   228 
   229 void EngineTestSuite::restore_full_env() {
   230     release(session);
   231     session = NULL;
   232         
   233     int success = 0;    
   234 
   235 #ifndef USE_NETPGP        
   236     success = system("gpgconf --kill all");
   237     if (success != 0)
   238         throw std::runtime_error("RESTORE: Error when executing 'gpgconf --kill all'.");
   239     success = system("gpgconf --remove-socketdir");            
   240     if (success != 0)
   241         throw std::runtime_error("RESTORE: Error when executing 'gpgconf --remove-socketdir'.");
   242 #endif
   243 
   244     success = setenv("GNUPGHOME", prev_pgp_home.c_str(), 1);
   245     if (success != 0)
   246         throw std::runtime_error("RESTORE: Warning - cannot restore GNUPGHOME. Either set environment variable manually back to your home, or quit this session!");
   247                 
   248     success = nftw((test_home + "/.").c_str(), util_delete_filepath, 100, FTW_DEPTH);
   249     
   250     success = setenv("HOME", real_home.c_str(), 1);
   251     if (success != 0)
   252         throw std::runtime_error("RESTORE: Cannot reset home directory! Either set environment variable manually back to your home, or quit this session!");
   253     // else
   254     //     cout << "RESTORE: HOME is now " << getenv("HOME") << endl;
   255     unix_local_db(true);
   256     gpg_conf(true);
   257     gpg_agent_conf(true);
   258 
   259 }
   260 
   261 void EngineTestSuite::setup() {
   262     on_test_number++;
   263 }
   264 
   265 void EngineTestSuite::tear_down() {}
   266 
   267 void EngineTestSuite::set_my_name() {
   268     my_name = typeid(*this).name();
   269 }