broken test sync-test-dev
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Fri, 04 Oct 2019 16:18:36 +0200
branchsync-test-dev
changeset 410836046fdf8106
parent 4106 3ca70862e37a
child 4116 2a81e6f6c53c
broken test
test/src/SyncTwoPartyTest.cc
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/test/src/SyncTwoPartyTest.cc	Fri Oct 04 16:18:36 2019 +0200
     1.3 @@ -0,0 +1,340 @@
     1.4 +#include <stdlib.h>
     1.5 +#include <string>
     1.6 +#include <cstring>
     1.7 +#include <ctime>
     1.8 +#include <deque>
     1.9 +
    1.10 +#include <sqlite3.h>
    1.11 +
    1.12 +#include <boost/interprocess/managed_shared_memory.hpp>
    1.13 +#include <boost/interprocess/containers/vector.hpp>
    1.14 +#include <boost/interprocess/allocators/allocator.hpp>
    1.15 +#include <boost/date_time/posix_time/posix_time.hpp>
    1.16 +
    1.17 +#include "pEpEngine.h"
    1.18 +#include "pEp_internal.h"
    1.19 +#include "sync_api.h"
    1.20 +#include "Sync_impl.h"
    1.21 +#include "mime.h"
    1.22 +
    1.23 +#include "test_util.h"
    1.24 +#include "TestConstants.h"
    1.25 +#include "Engine.h"
    1.26 +
    1.27 +
    1.28 +#include <gtest/gtest.h>
    1.29 +
    1.30 +using namespace boost::interprocess;
    1.31 +
    1.32 +//Define an STL compatible allocator of message* that allocates from the managed_shared_memory.
    1.33 +//This allocator will allow placing containers in the segment
    1.34 +typedef boost::interprocess::allocator<std::string, managed_shared_memory::segment_manager>  ShmemAllocator;
    1.35 +
    1.36 +//Alias a vector that uses the previous STL-like allocator so that allocates
    1.37 +//its values from the segment
    1.38 +typedef boost::interprocess::vector<std::string, ShmemAllocator> MailList;
    1.39 +
    1.40 +class LockedMailList
    1.41 +{
    1.42 +public:
    1.43 +    MailList vec;
    1.44 +    boost::interprocess::interprocess_mutex mutex;
    1.45 +
    1.46 +    LockedMailList(ShmemAllocator sm) 
    1.47 +       : vec(sm) 
    1.48 +    {}    
    1.49 +};
    1.50 +
    1.51 +
    1.52 +PEP_STATUS SyncTwoParty_message_send_callback(message* msg);
    1.53 +int SyncTwoParty_inject_sync_event(SYNC_EVENT ev, void *management);
    1.54 +SYNC_EVENT SyncTwoParty_retrieve_next_sync_event(void *management, unsigned threshold);
    1.55 +PEP_STATUS SyncTwoParty_notify_handshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal);
    1.56 +
    1.57 +static void* SyncTwoParty_fake_this;
    1.58 +
    1.59 +#define SyncTwoParty_segment_name "MessageQueueMem"
    1.60 +#define SyncTwoParty_vector_name "MessageQueue"
    1.61 +#define SyncTwoParty_locked_vector_name "LockedMessageQueue"
    1.62 +        
    1.63 +//The fixture for SyncTwoPartyTest
    1.64 +class SyncTwoPartyTest : public ::testing::Test {
    1.65 +    public:
    1.66 +        std::deque<SYNC_EVENT> ev_q;
    1.67 +        LockedMailList* mail_queue = NULL;
    1.68 +        const char* test_suite_name;
    1.69 +        std::string test_name;
    1.70 +        std::string test_path;
    1.71 +        // Objects declared here can be used by all tests in the SyncTwoPartyTest suite.
    1.72 +};
    1.73 +
    1.74 +
    1.75 +int SyncTwoParty_inject_sync_event(SYNC_EVENT ev, void *management)
    1.76 +{
    1.77 +    try {
    1.78 +        ((SyncTwoPartyTest*)SyncTwoParty_fake_this)->ev_q.push_front(ev);
    1.79 +    }
    1.80 +    catch (exception&) {
    1.81 +        return 1;
    1.82 +    }
    1.83 +    return 0;
    1.84 +}
    1.85 +
    1.86 +PEP_STATUS SyncTwoParty_message_send_callback(message* msg) {
    1.87 +    PEP_STATUS status = PEP_STATUS_OK;
    1.88 +    char* msg_str = NULL;
    1.89 +    mime_encode_message(msg, false, &msg_str);
    1.90 +    LockedMailList* lml = ((SyncTwoPartyTest*)SyncTwoParty_fake_this)->mail_queue;
    1.91 +    boost::posix_time::ptime end_time = boost::posix_time::second_clock::universal_time() + boost::posix_time::seconds(5);
    1.92 +    bool locked = lml->mutex.timed_lock(end_time);
    1.93 +    if (locked) {
    1.94 +        lml->vec.push_back(string(msg_str));
    1.95 +        lml->mutex.unlock();
    1.96 +    }    
    1.97 +    else 
    1.98 +        status = PEP_UNKNOWN_ERROR;
    1.99 +    free(msg_str);
   1.100 +    return status;
   1.101 +}
   1.102 +
   1.103 +// threshold: max waiting time in seconds
   1.104 +SYNC_EVENT SyncTwoParty_retrieve_next_sync_event(void *management, unsigned threshold)
   1.105 +{
   1.106 +    SYNC_EVENT syncEvent = nullptr;
   1.107 +        
   1.108 +    time_t start, curr;
   1.109 +    
   1.110 +    start = time(NULL);
   1.111 +    curr = start;
   1.112 +    
   1.113 +    while (curr - start < 10) {
   1.114 +        if (((SyncTwoPartyTest*)SyncTwoParty_fake_this)->ev_q.empty()) {
   1.115 +            sleep(1);
   1.116 +            curr = time(NULL);
   1.117 +            continue;
   1.118 +        }
   1.119 +        syncEvent = ((SyncTwoPartyTest*)SyncTwoParty_fake_this)->ev_q.front();
   1.120 +        ((SyncTwoPartyTest*)SyncTwoParty_fake_this)->ev_q.pop_front();
   1.121 +        break;
   1.122 +    }
   1.123 +    
   1.124 +    if (!syncEvent)
   1.125 +        return new_sync_timeout_event();
   1.126 +
   1.127 +    return syncEvent;
   1.128 +}
   1.129 +
   1.130 +PEP_STATUS SyncTwoParty_notify_handshake(
   1.131 +        pEp_identity *me,
   1.132 +        pEp_identity *partner,
   1.133 +        sync_handshake_signal signal
   1.134 +    )
   1.135 +{
   1.136 +    return PEP_STATUS_OK;
   1.137 +}
   1.138 +
   1.139 +TEST_F(SyncTwoPartyTest, check_sync_two_party) {
   1.140 +    sqlite3_initialize();
   1.141 +    test_suite_name = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name();
   1.142 +    test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
   1.143 +        
   1.144 +    int current_message_index = 0;
   1.145 +    
   1.146 +    pid_t pid = fork();
   1.147 +    
   1.148 +    managed_shared_memory segment;
   1.149 +    
   1.150 +    PEP_STATUS status = PEP_STATUS_OK;
   1.151 +    
   1.152 +    Engine* engine;
   1.153 +    PEP_SESSION session;
   1.154 +    
   1.155 +    // Create process specific variables and shared mail queue
   1.156 +    if (pid == 0) { // child
   1.157 +        sleep(1);
   1.158 +        test_name = (test_name + "_1");
   1.159 +        time_t start, curr;
   1.160 +
   1.161 +        start = time(NULL);
   1.162 +        curr = start;
   1.163 +        
   1.164 +        // Give the other process a while to set up the queue
   1.165 +        while (curr - start < 10) {
   1.166 +            // Try stuff here
   1.167 +            try {
   1.168 +                //Open the managed segment
   1.169 +                segment = managed_shared_memory(open_only, SyncTwoParty_segment_name);  
   1.170 +            }
   1.171 +            catch (interprocess_exception e) {    
   1.172 +                curr = time(NULL);
   1.173 +                continue;    
   1.174 +            }
   1.175 +            break;
   1.176 +        }   
   1.177 +
   1.178 +        if ((mail_queue = (segment.find<LockedMailList>(SyncTwoParty_locked_vector_name).first)) == NULL) {
   1.179 +            cerr << "CHILD UNABLE TO OPEN SHARED MEMORY SEGMENT" << endl;
   1.180 +            exit(-1);
   1.181 +        }
   1.182 +    }
   1.183 +    else if (pid > 0) { // parent
   1.184 +        test_name = (test_name + "_0");
   1.185 +        
   1.186 +        //Remove shared memory on construction and destruction        
   1.187 +        struct shm_remove {
   1.188 +            shm_remove() { shared_memory_object::remove(SyncTwoParty_segment_name); }
   1.189 +            ~shm_remove(){ shared_memory_object::remove(SyncTwoParty_segment_name); }
   1.190 +        } remover;
   1.191 +
   1.192 +        //Create a new segment with given name and size
   1.193 +        segment = managed_shared_memory(create_only, SyncTwoParty_segment_name, 1048576);
   1.194 +
   1.195 +        //Initialize shared memory STL-compatible allocator
   1.196 +        const ShmemAllocator alloc_inst(segment.get_segment_manager());
   1.197 +
   1.198 +        //Construct a vector named "MailList" in shared memory with argument alloc_inst
   1.199 +        mail_queue = segment.construct<LockedMailList>(SyncTwoParty_locked_vector_name)(alloc_inst);
   1.200 +    }
   1.201 +    else {
   1.202 +        // OMGWTFBBQ
   1.203 +        exit(-1);
   1.204 +    }
   1.205 +    
   1.206 +    // After this, this all happens in separate address spaces, so fake_this is safe
   1.207 +
   1.208 +    SyncTwoParty_fake_this = this;
   1.209 +    
   1.210 +    // Ok, now we're on to the independent stuff. We don't have to care about which device we are here.
   1.211 +    test_path = get_main_test_home_dir() + "/" + test_suite_name + "/" + test_name;
   1.212 +    cout << test_path << endl;
   1.213 +    
   1.214 +    std::vector<std::pair<std::string, std::string>> init_files = std::vector<std::pair<std::string, std::string>>();
   1.215 +
   1.216 +    // Get a new Engine.
   1.217 +    engine = new Engine(test_path);
   1.218 +    ASSERT_NE(engine, nullptr);
   1.219 +
   1.220 +    // Ok, let's initialize test directories etc.
   1.221 +    engine->prep(&SyncTwoParty_message_send_callback, &SyncTwoParty_inject_sync_event, init_files);
   1.222 +
   1.223 +
   1.224 +    // Ok, try to start this bugger for this fake device
   1.225 +    engine->start();
   1.226 +    ASSERT_NE(engine->session, nullptr);
   1.227 +    session = engine->session;
   1.228 +    
   1.229 +    // Fake device is ready to roll.
   1.230 +
   1.231 +    // Generate new identity for this device
   1.232 +    pEp_identity* me = new_identity("pickles@boofy.org", NULL, PEP_OWN_USERID, "Pickley Boofboof");
   1.233 +    status = myself(session, me);
   1.234 +    assert(status == PEP_STATUS_OK && me->fpr != NULL && me->fpr[0] != '\0');
   1.235 +
   1.236 +    status = register_sync_callbacks(session, NULL, &SyncTwoParty_notify_handshake, &SyncTwoParty_retrieve_next_sync_event);
   1.237 +
   1.238 +
   1.239 +    // If we need to step through, then do_sync_protocol_step here in a loop.
   1.240 +
   1.241 +    unsigned int last_message_index = 0;
   1.242 +    time_t prev_change = time(NULL);
   1.243 +    time_t now = prev_change;
   1.244 +    
   1.245 +    while (prev_change - now < (2 * SYNC_THRESHOLD)) {
   1.246 +        SYNC_EVENT event= NULL;
   1.247 +
   1.248 +        bool msg_received = false;
   1.249 +        bool event_processed = false;
   1.250 +        
   1.251 +        boost::posix_time::ptime end_time = boost::posix_time::second_clock::universal_time() + boost::posix_time::seconds(5);
   1.252 +        bool locked = mail_queue->mutex.timed_lock(end_time);
   1.253 +
   1.254 +        if (locked) {
   1.255 +            if (mail_queue->vec.size() > last_message_index) {
   1.256 +                message* next_msg = NULL;
   1.257 +                PEP_decrypt_flags_t flags = 0;
   1.258 +                PEP_rating rating;
   1.259 +                stringlist_t* keylist = NULL;
   1.260 +                std::string msg_str = mail_queue->vec.at(last_message_index++);
   1.261 +                message* actual_msg = NULL;
   1.262 +                mime_decode_message(msg_str.c_str(), msg_str.length(), &actual_msg);
   1.263 +                status = decrypt_message(session, actual_msg, &next_msg, &keylist, &rating, &flags);
   1.264 +                
   1.265 +                // FIXME: will need to be changed with sign_only
   1.266 +                assert(status == PEP_UNENCRYPTED || status == PEP_STATUS_OK);
   1.267 +                
   1.268 +                // If any checking of the message needs to happen, do it here.
   1.269 +                free_message(actual_msg);
   1.270 +                free_message(next_msg);
   1.271 +                msg_received = true;
   1.272 +            }
   1.273 +            mail_queue->mutex.unlock();
   1.274 +        }    
   1.275 +            
   1.276 +        event = session->retrieve_next_sync_event(session->sync_management,
   1.277 +                SYNC_THRESHOLD);
   1.278 +                
   1.279 +        if (event) {
   1.280 +            event_processed = true;
   1.281 +            do_sync_protocol_step(session, NULL, event);
   1.282 +        }    
   1.283 +        now = time(NULL);
   1.284 +        if (msg_received || event_processed)
   1.285 +            prev_change = now;
   1.286 +    } 
   1.287 +    
   1.288 +    unregister_sync_callbacks(session);
   1.289 +    
   1.290 +    if (pid > 0) {
   1.291 +        // Wait on dude to finish
   1.292 +        time_t start, curr;
   1.293 +        
   1.294 +        start = time(NULL);
   1.295 +        curr = start;
   1.296 +        
   1.297 +        // Give the other process time to exit
   1.298 +        while (curr - start < 10) {
   1.299 +            int status = 0;
   1.300 +            pid_t result = waitpid(pid, &status, WNOHANG);
   1.301 +            if (result > 0)
   1.302 +                break;
   1.303 +            sleep(1);    
   1.304 +            curr = time(NULL);    
   1.305 +        }   
   1.306 +        
   1.307 +        // When done, destroy the vector from the segment
   1.308 +        segment.destroy<LockedMailList>(SyncTwoParty_locked_vector_name);    
   1.309 +    }
   1.310 +    else {
   1.311 +        engine->shut_down();
   1.312 +        delete engine;
   1.313 +        engine = NULL;
   1.314 +        session = NULL;
   1.315 +
   1.316 +        exit(0);
   1.317 +    }
   1.318 +    
   1.319 +    // Note: this only checks the parent processes "device", but this doesn't much matter,
   1.320 +    // as over time, the parent will switch roles between offerer and requester during testing 
   1.321 +    // due to the randomness of TIDs.
   1.322 +    
   1.323 +    // are we now grouped?
   1.324 +    bool is_grouped = false;
   1.325 +    status = deviceGrouped(session, &is_grouped);
   1.326 +    ASSERT_TRUE(is_grouped);
   1.327 +    
   1.328 +    // check to see if we now have two keys
   1.329 +    stringlist_t* keylist = NULL;    
   1.330 +    status = own_keys_retrieve(session, &keylist);
   1.331 +    ASSERT_NE(keylist, nullptr);
   1.332 +    ASSERT_NE(keylist->value, nullptr);
   1.333 +    ASSERT_NE(keylist->next, nullptr);
   1.334 +    ASSERT_NE(keylist->value, nullptr);    
   1.335 +    ASSERT_EQ(keylist->next->next, nullptr);
   1.336 +    free_stringlist(keylist);
   1.337 +    
   1.338 +    engine->shut_down();
   1.339 +    delete engine;
   1.340 +    engine = NULL;
   1.341 +    session = NULL;
   1.342 +
   1.343 +}