1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
|
/*
* Copyright 2009- ECMWF.
*
* This software is licensed under the terms of the Apache Licence version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation
* nor does it submit to any jurisdiction.
*/
#include <boost/test/unit_test.hpp>
#include "MockServer.hpp"
#include "TestHelper.hpp"
#include "ecflow/base/cts/user/AlterCmd.hpp"
#include "ecflow/base/cts/user/ClientHandleCmd.hpp"
#include "ecflow/base/stc/SNewsCmd.hpp"
#include "ecflow/base/stc/SSyncCmd.hpp"
#include "ecflow/core/Converter.hpp"
#include "ecflow/core/Ecf.hpp"
#include "ecflow/node/Family.hpp"
#include "ecflow/node/Limit.hpp"
#include "ecflow/node/Suite.hpp"
#include "ecflow/node/SuiteChanged.hpp"
#include "ecflow/node/Task.hpp"
#include "ecflow/test/scaffold/Naming.hpp"
using namespace std;
using namespace ecf;
/// This test, is used to check sync with the client handles.
/// The client handles will register interest in a set of suites
/// When calling sync, check will only receive notification on our
/// our suites
// In particular when a set of suites are registered to a handle
// and we add/delete/check point/order the server passes back to the client
// the a *new* defs with all the suites corresponding to the handle
// There is a complication however, the suite are not copied/cloned
// This causes a problem, since if we create a new defs, and add
// the suites, the suite defs pointer is *NOW* corrupted, as it will point
// to the new defs. This is not an issue in real apps, since searisation
// fixes up these ptrs.
// The client handle commands do not change state & modify change number, hence need to bypass these checks
static bool bypass_state_modify_change_check = false;
BOOST_AUTO_TEST_SUITE(U_Base)
BOOST_AUTO_TEST_SUITE(T_SSyncCmd_CH1)
static defs_ptr create_client_defs(defs_ptr defs) {
for (size_t j = 0; j < 5; j++) {
suite_ptr suite = defs->add_suite("s" + ecf::convert_to<std::string>(j));
family_ptr f = suite->add_family("f");
f->add_task("t");
if (j == 0) {
suite->addLimit(Limit("suiteLimit", 10));
suite->addRepeat(RepeatDate("YMD", 20090916, 20090916, 1));
}
}
return defs;
}
static defs_ptr create_server_defs() {
defs_ptr defs = Defs::create();
// Create server defs, with a port other than default.
// This allows additional testing. i.e server variables
std::vector<Variable> server_variables;
ServerState::setup_default_server_variables(server_variables, "3141");
defs->server_state().set_server_variables(server_variables);
// ensure client/server start out the same
return create_client_defs(defs);
}
/// define a function which returns nothing, and takes a defs_ptr parameter
typedef boost::function<bool(defs_ptr)> defs_change_cmd;
/// Re-use the same test scaffold to modify and then resync, by passing
/// in a function that will modify the defs
void test_sync_scaffold(defs_change_cmd the_defs_change_command, const std::string& test_name, bool full_sync = false) {
// Create the defs
defs_ptr server_defs = create_server_defs();
ServerReply server_reply;
server_reply.set_client_defs(create_client_defs(Defs::create()));
Ecf::set_debug_equality(true); // only has affect in DEBUG build
BOOST_CHECK_MESSAGE(*server_defs == *server_reply.client_defs(),
test_name << ": Starting point client and server defs should be the same : "
<< "SERVER\n"
<< server_defs << "CLIENT\n"
<< server_reply.client_defs());
Ecf::set_debug_equality(false); // only has affect in DEBUG build
// set handle and change numbers, before any changes
Ecf::set_state_change_no(0);
Ecf::set_modify_change_no(0);
unsigned int client_state_change_no = Ecf::state_change_no();
unsigned int client_modify_change_no = Ecf::modify_change_no();
unsigned int client_handle = 0;
bool expected_change;
// make some change to the server
{
/// create client handle which references suites s0 and s4, in the server defs
/// Registering suites should change handle_changed boolean
std::vector<std::string> suite_names;
suite_names.emplace_back("s0");
suite_names.emplace_back("s4");
TestHelper::invokeRequest(
server_defs.get(), Cmd_ptr(new ClientHandleCmd(0, suite_names, false)), bypass_state_modify_change_check);
BOOST_CHECK_MESSAGE(server_defs->client_suite_mgr().clientSuites().size() == 1,
test_name << ": Expected 1 Client suites but found "
<< server_defs->client_suite_mgr().clientSuites().size());
client_handle = server_defs->client_suite_mgr().clientSuites().front().handle();
BOOST_CHECK_MESSAGE(client_handle == 1, "");
/// Check that handle_changed set, required for syncing, i.e needed for full sync , without change state/modify
/// numbers
BOOST_CHECK_MESSAGE(server_defs->client_suite_mgr().handle_changed(client_handle) == true,
"Expected handle_changed to be set when suites are registered ");
/// called create Defs should clear the flag. make sure server state, is synced
defs_ptr the_client_defs = server_defs->client_suite_mgr().create_defs(client_handle, server_defs);
BOOST_CHECK_MESSAGE(the_client_defs->suiteVec().size() == 2, test_name << ": Expected 2 suites");
BOOST_CHECK_MESSAGE(server_defs->client_suite_mgr().handle_changed(client_handle) == false,
test_name << ": Expected handle_changed to be cleared after create_defs()");
BOOST_CHECK_MESSAGE(server_defs->server_state().compare(the_client_defs->server_state()),
test_name << ": Server state does not match");
Ecf::set_server(true);
expected_change = the_defs_change_command(server_defs);
std::string error_msg;
BOOST_REQUIRE_MESSAGE(server_defs->checkInvariants(error_msg),
test_name << ": Invariants failed: " << error_msg);
Ecf::set_server(false);
/// Call create defs again, after change in server defs, check server state is synced
the_client_defs = server_defs->client_suite_mgr().create_defs(client_handle, server_defs);
BOOST_CHECK_MESSAGE(server_defs->server_state().compare(the_client_defs->server_state()),
test_name << ": Server state does not match");
BOOST_CHECK_MESSAGE(server_defs->get_flag() == the_client_defs->get_flag(),
test_name << ": Server flags do not match");
}
MockServer mock_server(server_defs);
SNewsCmd news_cmd(client_handle, client_state_change_no, client_modify_change_no, &mock_server);
SSyncCmd cmd(client_handle, client_state_change_no, client_modify_change_no, &mock_server);
if (expected_change) {
BOOST_CHECK_MESSAGE(news_cmd.get_news(), test_name << " : get_news : Expected server to change");
BOOST_CHECK_MESSAGE(cmd.do_sync(server_reply), test_name << " : do_sync : Expected server to change");
BOOST_CHECK_MESSAGE(server_reply.in_sync(), test_name << " : in_sync : Expected client server to be in sync");
BOOST_CHECK_MESSAGE(server_reply.full_sync() == full_sync,
test_name << ": Expected sync not as expected. client: " << server_reply.full_sync()
<< " full_sync: " << full_sync);
BOOST_CHECK_MESSAGE(server_defs->state() == server_reply.client_defs()->state(),
test_name << ": Expected server State(" << NState::toString(server_defs->state())
<< ") to be same as client state("
<< NState::toString(server_reply.client_defs()->state()) << ")");
if (full_sync) {
Ecf::set_debug_equality(true); // only has affect in DEBUG build
BOOST_CHECK_MESSAGE(server_defs->server_state().compare(server_reply.client_defs()->server_state()),
test_name << ": Server state does not match");
}
// * Note we expect client defs to fail invariant checking when doing a full sync with handles
// * Under real server this should be ok since, we fix up the defs ptr, during serialisation
// * note. We can't really compare server and client defs, since when we sync with
// * with handles, we only return a sub set of the suites, in our handle
// DO a sync again. hence we should expect no changes
server_reply.clear_for_invoke(false);
Ecf::set_server(true);
/* server side */ SNewsCmd news_cmd1(client_handle,
server_reply.client_defs()->state_change_no(),
server_reply.client_defs()->modify_change_no(),
&mock_server);
/* server side */ SSyncCmd cmd1(client_handle,
server_reply.client_defs()->state_change_no(),
server_reply.client_defs()->modify_change_no(),
&mock_server);
Ecf::set_server(false);
/* client side */ BOOST_CHECK_MESSAGE(!news_cmd1.get_news(),
test_name << ": Expected no changes to client, we should be in sync");
/* client side */ BOOST_CHECK_MESSAGE(!cmd1.do_sync(server_reply),
test_name << ": Expected no changes to client, we should be in sync");
}
else {
BOOST_CHECK_MESSAGE(!news_cmd.get_news(), test_name << ": Expected no change");
BOOST_CHECK_MESSAGE(!cmd.do_sync(server_reply), test_name << ": Expected no change");
BOOST_CHECK_MESSAGE(!server_reply.in_sync(), test_name << ": Expected no change");
BOOST_CHECK_MESSAGE(!(*server_defs == *server_reply.client_defs()),
test_name << ": Server and client defs expected to differ");
}
}
static bool set_server_state_shutdown(defs_ptr defs) {
defs->server_state().set_state(SState::SHUTDOWN);
return true; // expect changes
}
static bool set_server_state_running(defs_ptr defs) {
defs->server_state().set_state(SState::RUNNING);
return true; // expect changes
}
static bool set_defs_flag(defs_ptr defs) {
defs->flag().set(ecf::Flag::BYRULE);
defs->flag().set(ecf::Flag::EDIT_FAILED);
return true; // expect changes
}
static bool change_suites_s3_outside_of_handle(defs_ptr defs) {
/// Make a state change to suites s3, in the server. This is *not* in the client handle
/// Note: we do *NOT* make a state change as this will be propagated to the defs, and hence will be synced
/// We *NEED* MockSuiteChangedServer, so that change is propagated to the suite.
MockSuiteChangedServer mockServer(defs->findSuite("s3")); // Increment suite state/modify change number
defs->findSuite("s3")->suspend(); // small scale state change
return false; // expect no changes
}
static bool change_suites_s3_outside_of_handle_add_variable(defs_ptr defs) {
/// make a state change to suites s3, in the server. This is *not* in the client handle
/// We *NEED* MockSuiteChangedServer, so that change is propagated to the suite.
MockSuiteChangedServer mockServer(defs->findSuite("s3")); // Increment suite state/modify change number
defs->findSuite("s3")->add_variable("Var", "value"); // small scale state change
return false; // expect no changes in sync
}
static bool add_task_to_suite_s3(defs_ptr defs) {
/// make a modify change to suites s3, in the server. This is *not* in the client handle
MockSuiteChangedServer mockServer(defs->findSuite("s3")); // Increment suite state/modify change number
defs->findSuite("s3")->addTask(Task::create("s3_task")); // small scale change
return false; // expect no changes, since suite s3 not in handle
}
static bool delete_task_on_suite_s3(defs_ptr defs) {
/// make a modify change to suites s3, in the server. This is *not* in the client handle
MockSuiteChangedServer mockServer(defs->findSuite("s3")); // Increment suite state/modify change number
defs->findAbsNode("/s3/f/t")->remove(); // small scale change
return false; // expect no changes, since suite s3 not in handle
}
static bool delete_family_on_suite_s3(defs_ptr defs) {
/// make a modify change to suites s3, in the server. This is *not* in the client handle
MockSuiteChangedServer mockServer(defs->findSuite("s3")); // Increment suite state/modify change number
defs->findAbsNode("/s3/f")->remove(); // small scale change
return false; // expect no changes, since suite s3 not in handle
}
static bool change_state_of_s4(defs_ptr defs) {
/// Ok now make state change to s4, which **is** in the handle
/// We need MockSuiteChangedServer, so that change is propagated to the suite.
MockSuiteChangedServer mockServer(defs->findSuite("s4")); // Increment suite state/modify change number
defs->findSuite("s4")->set_state(NState::SUBMITTED); // small scale change
return true; // expect changes
}
static bool add_variable_to_suite_s4(defs_ptr defs) {
/// Ok now make state change to s4, which **is** in the handle
/// We need MockSuiteChangedServer, so that change is propagated to the suite.
MockSuiteChangedServer mockServer(defs->findSuite("s4")); // Increment suite state/modify change number
defs->findSuite("s4")->add_variable("Var", "value"); // small scale state change
return true; // expect changes
}
static bool add_server_user_variables(defs_ptr defs) {
// Change server. This is outside of any suites
std::vector<Variable> user_variables;
user_variables.emplace_back("a", "b");
user_variables.emplace_back("c", "d");
defs->server_state().set_user_variables(user_variables);
return true; // expect change
}
static bool add_task_to_suite_s4(defs_ptr defs) {
/// Ok now make modify change to s4, which **is** in the handle
MockSuiteChangedServer mockServer(defs->findSuite("s4")); // Increment suite state/modify change number
defs->findSuite("s4")->addTask(Task::create("s4_task")); // small scale change
return true; // expect changes
}
static bool delete_task_on_suite_s4(defs_ptr defs) {
/// Ok now make modify change to s4, which **is** in the handle
MockSuiteChangedServer mockServer(defs->findSuite("s4")); // Increment suite state/modify change number
defs->findAbsNode("/s4/f/t")->remove(); // small scale change
return true; // expect changes, since suite s4 is in handle
}
static bool delete_family_on_suite_s4(defs_ptr defs) {
/// Ok now make modify change to s4, which **is** in the handle
MockSuiteChangedServer mockServer(defs->findSuite("s4")); // Increment suite state/modify change number
defs->findAbsNode("/s4/f")->remove(); // small scale change
return true; // expect changes, since suite s4 is in handle
}
static bool change_order_of_s4_top(defs_ptr defs) {
/// Ok make modify change to s4, which **is** in the handle
suite_ptr s4 = defs->findSuite("s4");
MockSuiteChangedServer mockServer(s4); // Increment suite state/modify change number
defs->order(s4.get(), NOrder::TOP); // small scale scale change
return true;
}
static bool change_order_of_s4_bottom(defs_ptr defs) {
/// Ok make modify change to s4, which **is** in the handle
suite_ptr s4 = defs->findSuite("s4");
MockSuiteChangedServer mockServer(s4); // Increment suite state/modify change number
defs->order(s4.get(), NOrder::BOTTOM); // small scale change
return true;
}
static bool delete_suite_s4(defs_ptr defs) {
/// Ok now make delete s4 which, which **is** in the handle
MockSuiteChangedServer mockServer(defs->findSuite("s4")); // Increment suite state/modify change number
defs->findSuite("s4")->remove(); // large scale change
return true; // expect changes
}
static bool set_defs_state(defs_ptr defs) {
defs->set_state(NState::ABORTED); // changes the defs state
return true; // expect changes
}
static bool set_defs_state_2(defs_ptr defs) {
defs->set_state(NState::ABORTED); // changes the defs state
return delete_suite_s4(defs); // large scale change
}
static bool add_server_variable(defs_ptr defs) {
// Change defs server state. small scale change
TestHelper::invokeRequest(defs.get(), Cmd_ptr(new AlterCmd("/", AlterCmd::ADD_VARIABLE, "_fred_", "value")));
return true;
}
static bool change_server_variable(defs_ptr defs) {
// Because the scaffold create client/server defs each time.
// To test change/delete variables we modify the default set
TestHelper::invokeRequest(defs.get(), Cmd_ptr(new AlterCmd("/", AlterCmd::VARIABLE, "ECF_TRIES", "4")));
return true;
}
// ===============================================================================
// The modifiers, do this for suite s0 which is in a handle
// ===============================================================================
static bool s0_delete_some_attributes(defs_ptr defs) {
/// Ok now make state change to s4, which **is** in the handle
/// We need MockSuiteChangedServer, so that change is propagated to the suite.
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
std::vector<Task*> tasks;
suite->getAllTasks(tasks);
BOOST_REQUIRE_MESSAGE(!tasks.empty(), "Expected at least one task");
for (Task* task : tasks) {
SuiteChanged1 changed(task->suite());
task->addMeter(Meter("meter", 0, 100));
}
return true;
}
static bool s0_add_some_attributes(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
std::vector<task_ptr> tasks;
suite->get_all_tasks(tasks);
BOOST_REQUIRE_MESSAGE(!tasks.empty(), "Expected at least one task");
for (task_ptr task : tasks) {
SuiteChanged1 changed(suite.get());
task->addDay(DayAttr(DayAttr::TUESDAY));
}
return true;
}
static bool s0_begin(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
suite->begin();
return true;
}
static bool s0_add_alias(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
std::vector<task_ptr> tasks;
suite->get_all_tasks(tasks);
BOOST_REQUIRE_MESSAGE(!tasks.empty(), "Expected at least one task");
SuiteChanged1 changed(tasks[0]->suite());
tasks[0]->add_alias_only();
return true;
}
static bool s0_remove_all_tasks(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
// Remove tasks should force a incremental sync
std::vector<task_ptr> tasks;
suite->get_all_tasks(tasks);
BOOST_REQUIRE_MESSAGE(!tasks.empty(), "Expected at least one task");
for (task_ptr task : tasks) {
SuiteChanged1 changed(task->suite());
task->remove();
}
tasks.clear();
suite->get_all_tasks(tasks);
BOOST_REQUIRE_MESSAGE(tasks.empty(), "Failed to delete tasks");
return true;
}
static bool s0_remove_a_family(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
std::vector<Family*> vec;
suite->getAllFamilies(vec);
size_t family_size = vec.size();
BOOST_REQUIRE_MESSAGE(!vec.empty(), "Expected at least one family");
if (!vec.empty()) {
SuiteChanged1 changed(vec[0]->suite());
vec[0]->remove();
}
vec.clear();
suite->getAllFamilies(vec);
BOOST_REQUIRE_MESSAGE(vec.size() < family_size, "Failed to delete family");
return true;
}
static bool s0_change_clock_gain(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
suite->changeClockGain("100001");
return true;
}
static bool s0_change_clock_type_to_real(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
suite->changeClockType("hybrid");
return true;
}
static bool s0_change_clock_date(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
suite->changeClockDate("1.1.2001");
return true;
}
static bool s0_change_clock_sync(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
suite->changeClockSync();
return true;
}
/// This has been split into two functions, as changing both together could mask an error
/// i.e found bug where we forgot to update state_change number when changing the limit
/// max value, however because we had, changed value as well it got masked.
static bool s0_change_limit_max(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
// Note: we ONLY* need MockSuiteChangedServer, when we make changes via functions and not commands
std::vector<limit_ptr> theLimits = suite->limits();
BOOST_REQUIRE_MESSAGE(!theLimits.empty(), "The limit are empty on suite s0 " << defs);
for (limit_ptr l : theLimits) {
// std::cout << "found " << l->toString() << "\n";
TestHelper::invokeRequest(defs.get(),
Cmd_ptr(new AlterCmd(suite->absNodePath(), AlterCmd::LIMIT_MAX, l->name(), "90")));
limit_ptr v = suite->find_limit(l->name());
BOOST_CHECK_MESSAGE(v.get() && v->theLimit() == 90, "expected to find limit with max value of 90");
}
return true;
}
static bool s0_change_limit_value(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
// Note: we ONLY* need MockSuiteChangedServer, when we make changes via functions and not commands
std::vector<limit_ptr> theLimits = suite->limits();
for (limit_ptr l : theLimits) {
TestHelper::invokeRequest(defs.get(),
Cmd_ptr(new AlterCmd(suite->absNodePath(), AlterCmd::LIMIT_VAL, l->name(), "33")));
limit_ptr v = suite->find_limit(l->name());
BOOST_CHECK_MESSAGE(v.get() && v->value() == 33, "expected to find limit with value of 33");
}
return true;
}
static bool s0_update_repeat(defs_ptr defs) {
suite_ptr suite = defs->findSuite("s0");
BOOST_REQUIRE_MESSAGE(suite, "Could not find suite");
MockSuiteChangedServer mockServer(suite); // Increment suite state/modify change number
SuiteChanged1 changed(suite.get());
suite->increment_repeat();
return true;
}
BOOST_AUTO_TEST_CASE(test_ssync_using_handle) {
ECF_NAME_THIS_TEST();
TestLog test_log(
"test_ssync_using_handle.log"); // will create log file, and destroy log and remove file at end of scope
// =======================================================================================
// Note: where we update Suite::modify_change_no() we should *EXPECT* a full sync
// =======================================================================================
// test_sync_scaffold will created 5 suites s0,s1,s2,s3,s4,s5 and add suites s0 & s4 to a handle
// The following test will perform changes in/out of handles
{ // Change defs state in the presence of handles. These should sync regardless of handles
// The default server state is HALTED, hence setting to halted will not show a change
test_sync_scaffold(set_server_state_shutdown, "set_server_state_shutdown");
test_sync_scaffold(set_server_state_running, "set_server_state_running");
test_sync_scaffold(set_defs_flag, "set_defs_flag");
test_sync_scaffold(add_server_variable, "add_server_variable");
test_sync_scaffold(change_server_variable, "change_server_variable");
test_sync_scaffold(set_defs_state, "set_defs_state");
test_sync_scaffold(set_defs_state_2, "set_defs_state_2", true /* expect a full sync */);
}
test_sync_scaffold(change_suites_s3_outside_of_handle, "change_suites_s3_outside_of_handle");
test_sync_scaffold(change_suites_s3_outside_of_handle_add_variable,
"change_suites_s3_outside_of_handle_add_variable");
test_sync_scaffold(add_task_to_suite_s3, "add_task_to_suite_s3");
test_sync_scaffold(delete_task_on_suite_s3, "delete_task_on_suite_s3");
test_sync_scaffold(delete_family_on_suite_s3, "delete_family_on_suite_s3");
test_sync_scaffold(change_order_of_s4_top, "change_order_of_s4_top"); // change order is an incremental sync
test_sync_scaffold(change_order_of_s4_bottom, "change_order_of_s4_bottom"); // change order is an incremental sync
test_sync_scaffold(change_state_of_s4, "change_state_of_s4");
test_sync_scaffold(add_variable_to_suite_s4, "add_variable_to_suite_s4");
test_sync_scaffold(add_server_user_variables, "add_server_user_variables");
test_sync_scaffold(add_task_to_suite_s4, "add_task_to_suite_s4");
test_sync_scaffold(delete_task_on_suite_s4, "delete_task_on_suite_s4");
test_sync_scaffold(delete_family_on_suite_s4, "delete_family_on_suite_s4");
test_sync_scaffold(delete_suite_s4, "delete_suite_s4", true /* expect a full sync */);
test_sync_scaffold(s0_delete_some_attributes, "s0_delete_some_attributes");
test_sync_scaffold(s0_add_some_attributes, "s0_add_some_attributes");
test_sync_scaffold(s0_add_alias, "s0_add_alias");
test_sync_scaffold(s0_update_repeat, "s0_update_repeat");
test_sync_scaffold(s0_change_limit_max, "s0_change_limit_max");
test_sync_scaffold(s0_change_limit_value, "s0_change_limit_value");
test_sync_scaffold(s0_begin, "s0_begin", true /* expect a full sync */);
test_sync_scaffold(s0_remove_all_tasks, "s0_remove_all_tasks");
test_sync_scaffold(s0_remove_a_family, "s0_remove_a_family");
test_sync_scaffold(s0_change_clock_gain, "s0_change_clock_gain", true /* expect a full sync */);
test_sync_scaffold(s0_change_clock_type_to_real, "s0_change_clock_type_to_real", true /* expect a full sync */);
test_sync_scaffold(s0_change_clock_date, "s0_change_clock_date", true /* expect a full sync */);
test_sync_scaffold(s0_change_clock_sync, "s0_change_clock_sync", true /* expect a full sync */);
}
// =============================================================================================
static defs_ptr create_the_server_defs() {
defs_ptr defs = create_server_defs();
std::vector<suite_ptr> suite_vec = defs->suiteVec();
for (size_t j = 0; j < suite_vec.size(); j++) {
suite_vec[j]->set_state_change_no(j);
suite_vec[j]->set_modify_change_no(j);
}
return defs;
}
BOOST_AUTO_TEST_CASE(test_ssync_full_sync_using_handle) {
/// This test checks that when user has registered with all the suites.
/// Syncing should use the global change numbers
/// **ADDITIONALLY* the newsCmd must reflect this.
/// This is handled in ClientSuites::create_defs, in that we *MUST* update the
/// local change numbers to be the same as the global change numbers
/// This is important since the NewsCmd must be in *SYNC* with SYNCCmd
ECF_NAME_THIS_TEST();
TestLog test_log("test_ssync_full_sync_using_handle.log"); // will create log file, and destroy log and remove file
// at end of scope
// Create the server defs with some changes, in state & modify numbers
defs_ptr server_defs = create_the_server_defs();
// Create Client defs, without any changes
ServerReply server_reply;
server_reply.set_client_defs(create_client_defs(Defs::create()));
// Server & client should be the same, since we ignore change numbers in the comparison
DebugEquality debug_equality; // only as affect in DEBUG build
BOOST_CHECK_MESSAGE(*server_defs == *server_reply.client_defs(),
"Starting point client and server defs should be the same" << "SERVER\n"
<< server_defs << "CLIENT\n"
<< server_reply.client_defs());
/// register interest in **ALL** the suites
std::vector<std::string> suite_names;
suite_names.emplace_back("s0");
suite_names.emplace_back("s1");
suite_names.emplace_back("s2");
suite_names.emplace_back("s3");
suite_names.emplace_back("s4");
TestHelper::invokeRequest(
server_defs.get(), Cmd_ptr(new ClientHandleCmd(0, suite_names, false)), bypass_state_modify_change_check);
/// make sure handle created.
BOOST_CHECK_MESSAGE(server_defs->client_suite_mgr().clientSuites().size() == 1,
"Expected 1 Client suites but found " << server_defs->client_suite_mgr().clientSuites().size());
unsigned int client_handle = server_defs->client_suite_mgr().clientSuites().front().handle();
BOOST_CHECK_MESSAGE(client_handle == 1, "");
// make sure server suites have different state/modify numbers from the client
{
unsigned int server_state_change_no = 0;
unsigned int server_modify_change_no = 0;
server_defs->client_suite_mgr().max_change_no(client_handle, server_state_change_no, server_modify_change_no);
BOOST_CHECK_MESSAGE(server_state_change_no == 4, "");
BOOST_CHECK_MESSAGE(server_modify_change_no == 4, "");
// *MAKE* sure global change numbers are different to handle suite change numbers
// This is the key part of this test.
// Since syncing should transfer these change numbers to the client
Ecf::set_state_change_no(server_state_change_no + 10);
Ecf::set_modify_change_no(server_modify_change_no + 20);
}
// Now sync from server
Ecf::set_server(true);
MockServer mock_server(server_defs);
/* server side */ SNewsCmd news_cmd(client_handle,
server_reply.client_defs()->state_change_no(),
server_reply.client_defs()->modify_change_no(),
&mock_server);
/* server side */ SSyncCmd cmd(client_handle,
server_reply.client_defs()->state_change_no(),
server_reply.client_defs()->modify_change_no(),
&mock_server);
Ecf::set_server(false);
// make sure SSyncCmd updated the server change numbers, to use global change numbers
unsigned int server_state_change_no = 0;
unsigned int server_modify_change_no = 0;
{
server_defs->client_suite_mgr().max_change_no(client_handle, server_state_change_no, server_modify_change_no);
BOOST_CHECK_MESSAGE(server_state_change_no == 14, "");
BOOST_CHECK_MESSAGE(server_modify_change_no == 24, "");
}
// SYNC the client, via do_sync( this should transfer change numbers to the client )
BOOST_CHECK_MESSAGE(news_cmd.get_news(), "Expected server to change");
BOOST_CHECK_MESSAGE(cmd.do_sync(server_reply), "Expected server to change");
BOOST_CHECK_MESSAGE(server_reply.in_sync(), "Expected server to change");
BOOST_CHECK_MESSAGE(server_defs->state() == server_reply.client_defs()->state(),
"Expected server State(" << NState::toString(server_defs->state())
<< ") to be same as client state("
<< NState::toString(server_reply.client_defs()->state()) << ")");
// After do_sync client and server change number should be in sync
BOOST_CHECK_MESSAGE(server_reply.client_defs()->state_change_no() == server_state_change_no,
"Expected " << server_reply.client_defs()->state_change_no()
<< " state change number but found " << server_state_change_no);
BOOST_CHECK_MESSAGE(server_reply.client_defs()->modify_change_no() == server_modify_change_no,
"Expected " << server_reply.client_defs()->modify_change_no()
<< " modify change number but found " << server_modify_change_no);
// Do final sync, there should not be ANY changes
Ecf::set_server(true);
/* server side */ SNewsCmd news_cmd1(client_handle,
server_reply.client_defs()->state_change_no(),
server_reply.client_defs()->modify_change_no(),
&mock_server);
/* server side */ SSyncCmd cmd1(client_handle,
server_reply.client_defs()->state_change_no(),
server_reply.client_defs()->modify_change_no(),
&mock_server);
Ecf::set_server(false);
/* client side */ BOOST_CHECK_MESSAGE(!news_cmd1.get_news(), "Expected no changes to client, we should be in sync");
/* client side */ BOOST_CHECK_MESSAGE(!cmd1.do_sync(server_reply),
"Expected no changes to client, we should be in sync");
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()
|