File: TestCron.cpp

package info (click to toggle)
ecflow 5.15.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 51,868 kB
  • sloc: cpp: 269,341; python: 22,756; sh: 3,609; perl: 770; xml: 333; f90: 204; ansic: 141; makefile: 70
file content (146 lines) | stat: -rw-r--r-- 5,976 bytes parent folder | download
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
/*
 * 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 <cstdlib>
#include <fstream>
#include <iostream>

#include <boost/test/unit_test.hpp>

#include "ServerTestHarness.hpp"
#include "TestFixture.hpp"
#include "ecflow/attribute/VerifyAttr.hpp"
#include "ecflow/core/AssertTimer.hpp"
#include "ecflow/core/Chrono.hpp"
#include "ecflow/core/Timer.hpp"
#include "ecflow/node/Defs.hpp"
#include "ecflow/node/Family.hpp"
#include "ecflow/node/Suite.hpp"
#include "ecflow/node/Task.hpp"
#include "ecflow/node/formatter/DefsWriter.hpp"
#include "ecflow/test/scaffold/Naming.hpp"

using namespace ecf;

BOOST_AUTO_TEST_SUITE(S_Test)

BOOST_AUTO_TEST_SUITE(T_Cron)

static void wait_for_cron(int max_time_to_wait, const std::string& path) {
    AssertTimer assertTimer(max_time_to_wait, false); // Bomb out after n seconds, fall back if test fail
    TestFixture::client().set_throw_on_error(false);
    while (1) {
        BOOST_REQUIRE_MESSAGE(TestFixture::client().sync_local() == 0,
                              "sync_local failed should return 0\n"
                                  << TestFixture::client().errorMsg());
        defs_ptr defs = TestFixture::client().defs();
        if (defs) {
            node_ptr node = defs->findAbsNode(path);
            BOOST_REQUIRE_MESSAGE(node, "Could not find task at path " << path);
            if (node) {
                const std::vector<VerifyAttr>& verifys = node->verifys();
                BOOST_REQUIRE_MESSAGE(verifys.size() == 1, "Expected 1 verify");
                if (!verifys.empty()) {
                    if (verifys[0].actual() == verifys[0].expected()) {
                        break;
                    }
                }
            }
        }
        // make sure test does not take too long.
        if (assertTimer.duration() >= assertTimer.timeConstraint()) {
            BOOST_REQUIRE_MESSAGE(assertTimer.duration() < assertTimer.timeConstraint(),
                                  "wait_for_cron: Test wait " << assertTimer.duration()
                                                              << " taking longer than time constraint of "
                                                              << assertTimer.timeConstraint() << " aborting\n"
                                                              << ecf::as_string(*defs, PrintStyle::DEFS));
            break;
        }
        sleep(1);
    }
}

BOOST_AUTO_TEST_CASE(test_cron_time_series) {
    ECF_NAME_THIS_TEST();

    DurationTimer timer;
    TestClean clean_at_start_and_end;

    // SLOW SYSTEMS
    // for each time attribute leave GAP of 3 * job submission interval
    // on slow systems submitted->active->complete > TestFixture::job_submission_interval()
    // Also the task duration must be greater than job_submission_interval,  otherwise
    // we will get multiple invocation for the same time step

    // # Note: we have to use relative paths, since these tests are relocatable
    // suite test_cron_time_series
    //   edit SLEEPTIME 1
    //   edit ECF_INCLUDE $ECF_HOME/includes
    //   clock real <todays date>
    //   family family
    //     task t1
    //       cron <start> <finish> <incr>
    //   endfamily
    // endsuite
    Defs theDefs;
    std::string path;
    {
        // Initialise clock with todays date and time, then create a cron attribute
        // with a time series, so that task runs 3 times

        // Note: we don't use:
        //    auto theLocalTime = Calendar::second_clock_time();
        // Because this can fail with:
        //    Test:: ...test_cron_time_series unknown location(0): fatal error in
        //             "test_cron_time_series": std::out_of_range:
        //             TimeSeries::TimeSeries: Invalid time series: Start time(23:58) is greater than end time(00:02)
        // i.e
        // if the test is started at 23:58, then adding the end time of by doing start_time + 5 will fail the check
        auto theLocalTime =
            boost::posix_time::ptime(boost::gregorian::date(2010, 6, 21), boost::posix_time::time_duration(10, 0, 0));
        auto time1 = theLocalTime + boost::posix_time::minutes(1);
        auto time2 = theLocalTime + boost::posix_time::minutes(5);

        suite_ptr suite = theDefs.add_suite("test_cron_time_series");
        ClockAttr clockAttr(theLocalTime, false);
        suite->addClock(clockAttr);

        family_ptr fam = suite->add_family("family");
        task_ptr task  = fam->add_task("t");
        task->addVerify(VerifyAttr(NState::COMPLETE, 3)); // task should complete 3 times

        CronAttr cronAttr;
        cronAttr.addTimeSeries(
            ecf::TimeSlot(time1.time_of_day()), ecf::TimeSlot(time2.time_of_day()), ecf::TimeSlot(0, 2));
        task->addCron(cronAttr);

        path = task->absNodePath();
    }

    // The test harness will create corresponding directory structure
    // and populate with standard ecf files.
    ServerTestHarness serverTestHarness;
    serverTestHarness.add_default_sleep_time(
        false); // avoid missing time steps due to submit->active->complete > job submission interval
    serverTestHarness.run(theDefs,
                          ServerTestHarness::testDataDefsLocation("test_cron_time_series.def"),
                          1 /* timeout ignored*/,
                          false /*waitForTestCompletion*/);

    // crons are *infinite*, just wait for cron to complete 3 times
    wait_for_cron(40, path);

    std::cout << timer.duration() << " update-calendar-count(" << serverTestHarness.serverUpdateCalendarCount()
              << ")\n";
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()