test/src/engine_tests/SyncTests.cc
author Volker Birk <vb@pep-project.org>
Thu, 06 Jun 2019 22:34:31 +0200
branchsync
changeset 3818 0b34a967ab39
parent 3817 c2cb0ab6040a
child 3834 2934fc35d7a3
permissions -rw-r--r--
rollback
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #include <stdlib.h>
     5 #include <string>
     6 #include <assert.h>
     7 #include <cpptest.h>
     8 #include "test_util.h"
     9 
    10 #include "pEpEngine.h"
    11 
    12 #include "pEp_internal.h"
    13 #include "KeySync_fsm.h"
    14 #include "sync_codec.h"
    15 
    16 #include "EngineTestSessionSuite.h"
    17 #include "SyncTests.h"
    18 
    19 using namespace std;
    20 
    21 void Sync_Adapter::processing()
    22 {
    23     cout << "waiting for processing\n";
    24     while (!q.empty()) {
    25         nanosleep((const struct timespec[]){{0, 100000000L}}, NULL);
    26     }
    27 }
    28 
    29 PEP_STATUS Sync_Adapter::notifyHandshake(
    30         pEp_identity *me,
    31         pEp_identity *partner,
    32         sync_handshake_signal signal
    33     )
    34 {
    35     return PEP_STATUS_OK;
    36 }
    37 
    38 int Sync_Adapter::inject_sync_event(SYNC_EVENT ev, void *management)
    39 {
    40     Sync_event_t *_ev = ev;
    41     switch (_ev->fsm) {
    42         case Sync_PR_keysync:
    43             cout << "injecting event " << KeySync_event_name(_ev->event) << "\n";
    44             break;
    45         default:
    46             cout << "unknown state machine: " << _ev->fsm << "\n";
    47             assert(0);
    48     }
    49     auto adapter = static_cast< Sync_Adapter *>(management);
    50     adapter->q.push_front(ev);
    51     return 0;
    52 }
    53 
    54 Sync_event_t *Sync_Adapter::retrieve_next_sync_event(void *management, unsigned threshold)
    55 {
    56     auto adapter = static_cast< Sync_Adapter *>(management);
    57     time_t started = time(nullptr);
    58     bool timeout = false;
    59 
    60     while (adapter->q.empty()) {
    61         int i = 0;
    62         ++i;
    63         if (i > 10) {
    64             if (time(nullptr) > started + threshold) {
    65                 timeout = true;
    66                 break;
    67             }
    68             i = 0;
    69         }
    70         nanosleep((const struct timespec[]){{0, 100000000L}}, NULL);
    71     }
    72 
    73     if (timeout)
    74         return SYNC_TIMEOUT_EVENT;
    75 
    76     Sync_event_t *ev = adapter->q.pop_front();
    77     if (ev) {
    78         switch (ev->fsm) {
    79             case Sync_PR_keysync:
    80                 cout << "sync thread: retrieving event " << KeySync_event_name(ev->event) << "\n";
    81                 break;
    82             default:
    83                 cout << "sync thread: unknown state machine: " << ev->fsm << "\n";
    84                 assert(0);
    85         }
    86     }
    87     else {
    88         cout << "sync thread: retrieving shutdown\n";
    89     }
    90 
    91     return ev;
    92 }
    93 
    94 PEP_STATUS Sync_Adapter::messageToSend(struct _message *msg)
    95 {
    96     assert(msg && msg->attachments);
    97     
    98     cout << "sending message:\n";
    99 
   100     for (bloblist_t *b = msg->attachments; b && b->value; b = b->next) {
   101         if (b->mime_type && strcasecmp(b->mime_type, "application/pEp.sync") == 0) {
   102             assert(msg->from && msg->from->address && msg->from->username);
   103             cout << "<!-- " << msg->from->username << " <" << msg->from->address << "> -->\n";
   104             char *text = NULL;
   105             PEP_STATUS status = PER_to_XER_Sync_msg(msg->attachments->value, msg->attachments->size, &text);
   106             assert(status == PEP_STATUS_OK);
   107             cout << text << "\n";
   108             free(text);
   109         }
   110     }
   111 
   112     free_message(msg);
   113     return PEP_STATUS_OK;
   114 }
   115 
   116 void Sync_Adapter::sync_thread(PEP_SESSION session, Sync_Adapter *adapter)
   117 {
   118     cout << "sync_thread: startup\n";
   119     do_sync_protocol(session, adapter);
   120     cout << "sync_thread: shutdown\n";
   121 }
   122 
   123 SyncTests::SyncTests(string suitename, string test_home_dir) :
   124     EngineTestSessionSuite::EngineTestSessionSuite(suitename, test_home_dir) {
   125     add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("SyncTests::check_sync"),
   126                                                                       static_cast<Func>(&SyncTests::check_sync)));
   127 }
   128 
   129 void SyncTests::setup()
   130 {
   131     EngineTestSessionSuite::setup();
   132 
   133     pEp_identity *self = new_identity("alice@synctests.pEp", nullptr, "23", "Alice Miller");
   134     assert(self);
   135     cout << "setting own identity for " << self->address << "\n";
   136     PEP_STATUS status = myself(session, self);
   137     assert(self->me);
   138     assert(self->fpr);
   139     cout << "fpr: " << self->fpr << "\n";
   140     free_identity(self);
   141 
   142     status = init(&sync, Sync_Adapter::messageToSend, Sync_Adapter::inject_sync_event);
   143     if (status != PEP_STATUS_OK)
   144         throw std::runtime_error((string("init returned ") + tl_status_string(status)).c_str()); 
   145 
   146     cout << "initialize sync and start first state machine\n";
   147     status = register_sync_callbacks(
   148             sync,
   149             (void *) &adapter.q,
   150             Sync_Adapter::notifyHandshake,
   151             Sync_Adapter::retrieve_next_sync_event
   152         );
   153     if (status != PEP_STATUS_OK)
   154         throw std::runtime_error((string("register sync status returned ") + tl_status_string(status)).c_str()); 
   155     if (sync->sync_state.keysync.state != Sole) 
   156         throw std::runtime_error((string("keysync.state was supposed to be ") + to_string((int)Sole) + " but was " + to_string((int)(sync->sync_state.keysync.state))).c_str()); 
   157       
   158 
   159     cout << "creating thread for sync\n";
   160     sync_thread = new thread(Sync_Adapter::sync_thread, sync, &adapter);
   161 }
   162 
   163 void SyncTests::tear_down()
   164 {
   165     adapter.processing();
   166 
   167     cout << "sending shutdown to sync thread\n";
   168     adapter.q.push_front(nullptr);
   169     sync_thread->join();
   170 
   171     unregister_sync_callbacks(sync);
   172     release(sync);
   173 
   174     EngineTestSessionSuite::tear_down();
   175 }
   176 
   177 void SyncTests::check_sync()
   178 {
   179     cout << "check_sync(): trigger KeyGen event\n";
   180     signal_Sync_event(sync, Sync_PR_keysync, KeyGen, NULL);
   181     adapter.processing();
   182 
   183     cout << "check_sync(): cry for unknown key\n";
   184     signal_Sync_event(sync, Sync_PR_keysync, CannotDecrypt, NULL);
   185 }