1 /*
2  * Copyright (C) 2009-2020 Codership Oy <info@codership.com>
3  */
4 
5 #include "gcomm/util.hpp"
6 #include "gcomm/protonet.hpp"
7 #include "gcomm/datagram.hpp"
8 #include "gcomm/conf.hpp"
9 
10 #include "check_gcomm.hpp"
11 
12 #include "gu_logger.hpp"
13 
14 #include <vector>
15 #include <fstream>
16 #include <limits>
17 #include <cstdlib>
18 #include <check.h>
19 
20 using std::vector;
21 using std::numeric_limits;
22 using std::string;
23 
24 using namespace gcomm;
25 using gu::Exception;
26 using gu::byte_t;
27 using gu::Buffer;
28 
START_TEST(test_datagram)29 START_TEST(test_datagram)
30 {
31 
32     // Header check
33     gcomm::NetHeader hdr(42, 0);
34     ck_assert(hdr.len() == 42);
35     ck_assert(hdr.has_crc32() == false);
36     ck_assert(hdr.version() == 0);
37 
38     hdr.set_crc32(1234, NetHeader::CS_CRC32);
39     ck_assert(hdr.has_crc32() == true);
40     ck_assert(hdr.len() == 42);
41 
42     gcomm::NetHeader hdr1(42, 1);
43     ck_assert(hdr1.len() == 42);
44     ck_assert(hdr1.has_crc32() == false);
45     ck_assert(hdr1.version() == 1);
46 
47     gu::byte_t hdrbuf[NetHeader::serial_size_];
48     ck_assert(serialize(hdr1, hdrbuf, sizeof(hdrbuf), 0) ==
49                 NetHeader::serial_size_);
50     try
51     {
52         unserialize(hdrbuf, sizeof(hdrbuf), 0, hdr);
53         ck_abort();
54     }
55     catch (Exception& e)
56     {
57         // ok
58     }
59 
60 
61     gu::byte_t b[128];
62     for (gu::byte_t i = 0; i < sizeof(b); ++i)
63     {
64         b[i] = i;
65     }
66     gu::Buffer buf(b, b + sizeof(b));
67 
68     gcomm::Datagram dg(buf);
69     ck_assert(dg.len() == sizeof(b));
70 
71     // Normal copy construction
72     gcomm::Datagram dgcopy(buf);
73     ck_assert(dgcopy.len() == sizeof(b));
74     ck_assert(memcmp(dgcopy.header() + dgcopy.header_offset(),
75                        dg.header() + dg.header_offset(),
76                        dg.header_len()) == 0);
77     ck_assert(dgcopy.payload() == dg.payload());
78 
79     // Copy construction from offset of 16
80     gcomm::Datagram dg16(dg, 16);
81     log_info << dg16.len();
82     ck_assert(dg16.len() - dg16.offset() == sizeof(b) - 16);
83     for (gu::byte_t i = 0; i < sizeof(b) - 16; ++i)
84     {
85         ck_assert(dg16.payload()[i + dg16.offset()] == i + 16);
86     }
87 
88 #if 0
89     // Normalize datagram, all data is moved into payload, data from
90     // beginning to offset is discarded. Normalization must not change
91     // dg
92     dg16.normalize();
93 
94     ck_assert(dg16.len() == sizeof(b) - 16);
95     for (byte_t i = 0; i < sizeof(b) - 16; ++i)
96     {
97         ck_assert(dg16.payload()[i] == i + 16);
98     }
99 
100     ck_assert(dg.len() == sizeof(b));
101     for (byte_t i = 0; i < sizeof(b); ++i)
102     {
103         ck_assert(dg.payload()[i] == i);
104     }
105 
106     Datagram dgoff(buf, 16);
107     dgoff.header().resize(8);
108     dgoff.set_header_offset(4);
109     ck_assert(dgoff.len() == buf.size() + 4);
110     ck_assert(dgoff.header_offset() == 4);
111     ck_assert(dgoff.header().size() == 8);
112     for (byte_t i = 0; i < 4; ++i)
113     {
114         *(&dgoff.header()[0] + i) = i;
115     }
116 
117     dgoff.normalize();
118 
119     ck_assert(dgoff.len() == sizeof(b) - 16 + 4);
120     ck_assert(dgoff.header_offset() == 0);
121     ck_assert(dgoff.header().size() == 0);
122 #endif // 0
123 }
124 END_TEST
125 
126 
127 
128 
START_TEST(test_view_state)129 START_TEST(test_view_state)
130 {
131     // compare view.
132     UUID view_uuid(NULL, 0);
133     ViewId view_id(V_TRANS, view_uuid, 789);
134     UUID m1(NULL, 0);
135     UUID m2(NULL, 0);
136     View view(0, view_id, true);
137     view.add_member(m1, 0);
138     view.add_member(m2, 1);
139     View view2;
140 
141     {
142         std::ostringstream os;
143         view.write_stream(os);
144 
145         std::istringstream is(os.str());
146         view2.read_stream(is);
147 
148         ck_assert(view == view2);
149     }
150 
151     // Create configuration to set file name.
152     gu::Config conf;
153 
154     // compare view state.
155     UUID my_uuid(NULL, 0);
156     ViewState vst(my_uuid, view, conf);
157     UUID my_uuid_2;
158     View view_2;
159     ViewState vst2(my_uuid_2, view_2, conf);
160 
161     {
162         std::ostringstream os;
163         vst.write_stream(os);
164 
165         std::istringstream is(os.str());
166         vst2.read_stream(is);
167 
168         ck_assert(vst == vst2);
169     }
170 
171     // test write file and read file.
172     vst.write_file();
173     UUID my_uuid_3;
174     View view_3;
175     ViewState vst3(my_uuid_3, view_3, conf);
176     vst3.read_file();
177     ck_assert(vst == vst3);
178     ViewState::remove_file(conf);
179 }
180 END_TEST
181 
182 
util_suite()183 Suite* util_suite()
184 {
185     Suite* s = suite_create("util");
186     TCase* tc;
187 
188     tc = tcase_create("test_datagram");
189     tcase_add_test(tc, test_datagram);
190     suite_add_tcase(s, tc);
191 
192     tc = tcase_create("test_view_state");
193     tcase_add_test(tc, test_view_state);
194     suite_add_tcase(s, tc);
195 
196     return s;
197 }
198