libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers log.cpp Source File

log.cpp

00001 /*
00002  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #include <gtest/gtest.h>
00006 #include <uavcan/protocol/dynamic_node_id_server/distributed/log.hpp>
00007 #include "../event_tracer.hpp"
00008 #include "../../helpers.hpp"
00009 #include "../memory_storage_backend.hpp"
00010 
00011 
00012 static const unsigned NumEntriesInStorageWithEmptyLog = 4;  // last index + 3 items per log entry
00013 
00014 
00015 TEST(dynamic_node_id_server_Log, Initialization)
00016 {
00017     using namespace uavcan::dynamic_node_id_server::distributed;
00018 
00019     EventTracer tracer;
00020     // No log data in the storage - initializing empty log
00021     {
00022         MemoryStorageBackend storage;
00023         uavcan::dynamic_node_id_server::distributed::Log log(storage, tracer);
00024 
00025         ASSERT_EQ(0, storage.getNumKeys());
00026         ASSERT_LE(0, log.init());
00027         ASSERT_EQ(NumEntriesInStorageWithEmptyLog, storage.getNumKeys());
00028         ASSERT_EQ(0, log.getLastIndex());
00029         ASSERT_EQ(0, log.getEntryAtIndex(0)->term);
00030         ASSERT_EQ(0, log.getEntryAtIndex(0)->node_id);
00031         ASSERT_EQ(uavcan::protocol::dynamic_node_id::server::Entry::FieldTypes::unique_id(),
00032                   log.getEntryAtIndex(0)->unique_id);
00033     }
00034     // Nonempty storage, one item
00035     {
00036         MemoryStorageBackend storage;
00037         Log log(storage, tracer);
00038 
00039         storage.set("log_last_index", "0");
00040         ASSERT_LE(-uavcan::ErrFailure, log.init());     // Expected one entry, none found
00041         ASSERT_EQ(1, storage.getNumKeys());
00042 
00043         storage.set("log0_term",      "0");
00044         storage.set("log0_unique_id", "00000000000000000000000000000000");
00045         storage.set("log0_node_id",   "0");
00046         ASSERT_LE(0, log.init());                       // OK now
00047         ASSERT_EQ(NumEntriesInStorageWithEmptyLog, storage.getNumKeys());
00048         ASSERT_EQ(0, log.getLastIndex());
00049         ASSERT_EQ(0, log.getEntryAtIndex(0)->term);
00050     }
00051     // Nonempty storage, broken data
00052     {
00053         MemoryStorageBackend storage;
00054         Log log(storage, tracer);
00055 
00056         storage.set("log_last_index", "foobar");
00057         ASSERT_LE(-uavcan::ErrFailure, log.init());     // Bad value
00058 
00059         storage.set("log_last_index", "128");
00060         ASSERT_LE(-uavcan::ErrFailure, log.init());     // Bad value
00061 
00062         storage.set("log_last_index", "0");
00063         ASSERT_LE(-uavcan::ErrFailure, log.init());     // No log items
00064         ASSERT_EQ(1, storage.getNumKeys());
00065 
00066         storage.set("log0_term",      "0");
00067         storage.set("log0_unique_id", "00000000000000000000000000000000");
00068         storage.set("log0_node_id",   "128");           // Bad value (127 max)
00069         ASSERT_LE(-uavcan::ErrFailure, log.init());     // Failed
00070         ASSERT_EQ(0, log.getLastIndex());
00071         ASSERT_EQ(0, log.getEntryAtIndex(0)->term);
00072         ASSERT_EQ(4, storage.getNumKeys());
00073     }
00074     // Nonempty storage, many items
00075     {
00076         MemoryStorageBackend storage;
00077         Log log(storage, tracer);
00078 
00079         storage.set("log_last_index", "1");  // 2 items - 0, 1
00080         storage.set("log0_term",      "0");
00081         storage.set("log0_unique_id", "00000000000000000000000000000000");
00082         storage.set("log0_node_id",   "0");
00083         storage.set("log1_term",      "1");
00084         storage.set("log1_unique_id", "0123456789abcdef0123456789abcdef");
00085         storage.set("log1_node_id",   "127");
00086 
00087         ASSERT_LE(0, log.init());                       // OK now
00088         ASSERT_EQ(7, storage.getNumKeys());
00089         ASSERT_EQ(1, log.getLastIndex());
00090 
00091         ASSERT_EQ(0, log.getEntryAtIndex(0)->term);
00092         ASSERT_EQ(0, log.getEntryAtIndex(0)->node_id);
00093         ASSERT_EQ(uavcan::protocol::dynamic_node_id::server::Entry::FieldTypes::unique_id(),
00094                   log.getEntryAtIndex(0)->unique_id);
00095 
00096         ASSERT_EQ(1, log.getEntryAtIndex(1)->term);
00097         ASSERT_EQ(127, log.getEntryAtIndex(1)->node_id);
00098         uavcan::protocol::dynamic_node_id::server::Entry::FieldTypes::unique_id uid;
00099         uid[0] = 0x01;
00100         uid[1] = 0x23;
00101         uid[2] = 0x45;
00102         uid[3] = 0x67;
00103         uid[4] = 0x89;
00104         uid[5] = 0xab;
00105         uid[6] = 0xcd;
00106         uid[7] = 0xef;
00107         uavcan::copy(uid.begin(), uid.begin() + 8, uid.begin() + 8);
00108         ASSERT_EQ(uid, log.getEntryAtIndex(1)->unique_id);
00109     }
00110 }
00111 
00112 
00113 TEST(dynamic_node_id_server_Log, Append)
00114 {
00115     using namespace uavcan::dynamic_node_id_server::distributed;
00116 
00117     EventTracer tracer;
00118     MemoryStorageBackend storage;
00119     Log log(storage, tracer);
00120 
00121     ASSERT_EQ(0, storage.getNumKeys());
00122     ASSERT_LE(0, log.init());
00123     storage.print();
00124     ASSERT_EQ(NumEntriesInStorageWithEmptyLog, storage.getNumKeys());
00125 
00126     /*
00127      * Entry at the index 0 always exists, and it's always zero-initialized.
00128      */
00129     ASSERT_EQ("0",                                storage.get("log_last_index"));
00130     ASSERT_EQ("0",                                storage.get("log0_term"));
00131     ASSERT_EQ("00000000000000000000000000000000", storage.get("log0_unique_id"));
00132     ASSERT_EQ("0",                                storage.get("log0_node_id"));
00133 
00134     /*
00135      * Adding one entry to the log, making sure it appears in the storage
00136      */
00137     uavcan::protocol::dynamic_node_id::server::Entry entry;
00138     entry.term = 1;
00139     entry.node_id = 1;
00140     entry.unique_id[0] = 1;
00141     ASSERT_LE(0, log.append(entry));
00142 
00143     ASSERT_EQ("1",                                storage.get("log_last_index"));
00144     ASSERT_EQ("1",                                storage.get("log1_term"));
00145     ASSERT_EQ("01000000000000000000000000000000", storage.get("log1_unique_id"));
00146     ASSERT_EQ("1",                                storage.get("log1_node_id"));
00147 
00148     ASSERT_EQ(1, log.getLastIndex());
00149     ASSERT_TRUE(entry == *log.getEntryAtIndex(1));
00150 
00151     /*
00152      * Adding another entry while storage is failing
00153      */
00154     storage.failOnSetCalls(true);
00155 
00156     ASSERT_EQ(7, storage.getNumKeys());
00157 
00158     entry.term = 2;
00159     entry.node_id = 2;
00160     entry.unique_id[0] = 2;
00161     ASSERT_GT(0, log.append(entry));
00162 
00163     ASSERT_EQ(7, storage.getNumKeys());  // No new entries, we failed
00164 
00165     ASSERT_EQ(1, log.getLastIndex());
00166 
00167     /*
00168      * Making sure append() fails when the log is full
00169      */
00170     storage.failOnSetCalls(false);
00171 
00172     while (log.getLastIndex() < (log.Capacity - 1))
00173     {
00174         ASSERT_LE(0, log.append(entry));
00175         ASSERT_TRUE(entry == *log.getEntryAtIndex(log.getLastIndex()));
00176 
00177         entry.term += 1;
00178         entry.node_id = uint8_t(entry.node_id + 1U);
00179         entry.unique_id[0] = uint8_t(entry.unique_id[0] + 1U);
00180     }
00181 
00182     ASSERT_GT(0, log.append(entry));  // Failing because full
00183 
00184     storage.print();
00185 }
00186 
00187 
00188 TEST(dynamic_node_id_server_Log, Remove)
00189 {
00190     using namespace uavcan::dynamic_node_id_server::distributed;
00191 
00192     EventTracer tracer;
00193     MemoryStorageBackend storage;
00194     Log log(storage, tracer);
00195 
00196     /*
00197      * Filling the log fully
00198      */
00199     uavcan::protocol::dynamic_node_id::server::Entry entry;
00200     entry.term = 1;
00201     entry.node_id = 1;
00202     entry.unique_id[0] = 1;
00203 
00204     while (log.getLastIndex() < (log.Capacity - 1))
00205     {
00206         ASSERT_LE(0, log.append(entry));
00207         ASSERT_TRUE(entry == *log.getEntryAtIndex(log.getLastIndex()));
00208 
00209         entry.term += 1;
00210         entry.node_id = uint8_t(entry.node_id + 1U);
00211         entry.unique_id[0] = uint8_t(entry.unique_id[0] + 1U);
00212     }
00213 
00214     /*
00215      * Removal will fail as the storage is failing to update
00216      */
00217     storage.failOnSetCalls(true);
00218 
00219     ASSERT_EQ(log.Capacity - 1, log.getLastIndex());
00220     ASSERT_GT(0, log.removeEntriesWhereIndexGreaterOrEqual(60));  // Failing
00221     ASSERT_EQ(log.Capacity - 1, log.getLastIndex());
00222 
00223     /*
00224      * Now removal must work
00225      */
00226     storage.failOnSetCalls(false);
00227 
00228     ASSERT_EQ(log.Capacity - 1, log.getLastIndex());
00229 
00230     ASSERT_LE(0, log.removeEntriesWhereIndexGreaterOrEqual(60));
00231     ASSERT_EQ(59, log.getLastIndex());
00232     ASSERT_EQ("59", storage.get("log_last_index"));
00233 
00234     ASSERT_LE(0, log.removeEntriesWhereIndexGreater(30));
00235     ASSERT_EQ(30, log.getLastIndex());
00236     ASSERT_EQ("30", storage.get("log_last_index"));
00237 
00238     ASSERT_LE(0, log.removeEntriesWhereIndexGreaterOrEqual(1));
00239     ASSERT_EQ(0, log.getLastIndex());
00240     ASSERT_EQ("0", storage.get("log_last_index"));
00241 
00242     storage.print();
00243 }