MB-24293: Retry atmost 10 times if directory removal fails
[ep-engine.git] / tests / module_tests / evp_engine_test.cc
1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 Couchbase, Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17
18 /*
19  * Unit tests for the EventuallyPersistentEngine class.
20  */
21
22 #include "evp_engine_test.h"
23
24 #include "ep_engine.h"
25 #include "programs/engine_testapp/mock_server.h"
26 #include "tests/module_tests/test_helpers.h"
27
28 #include <configuration_impl.h>
29 #include <platform/dirutils.h>
30
31 void EventuallyPersistentEngineTest::SetUp() {
32     // Paranoia - kill any existing files in case they are left over
33     // from a previous run.
34     try {
35         cb::io::rmrf(test_dbname);
36     } catch (std::system_error& e) {
37         if (e.code() != std::error_code(ENOENT, std::system_category())) {
38             throw e;
39         }
40     }
41
42     // Setup an engine with a single active vBucket.
43     EXPECT_EQ(ENGINE_SUCCESS,
44               create_instance(1, get_mock_server_api, &handle))
45         << "Failed to create ep engine instance";
46     EXPECT_EQ(1, handle->interface) << "Unexpected engine handle version";
47     engine_v1 = reinterpret_cast<ENGINE_HANDLE_V1*>(handle);
48
49     engine = reinterpret_cast<EventuallyPersistentEngine*>(handle);
50     ObjectRegistry::onSwitchThread(engine);
51
52     // Add dbname to config string.
53     std::string config = config_string;
54     if (config.size() > 0) {
55         config += ";";
56     }
57     config += "dbname=" + std::string(test_dbname);
58
59     // Set the bucketType
60     config += ";bucket_type=" + bucketType;
61
62     EXPECT_EQ(ENGINE_SUCCESS, engine->initialize(config.c_str()))
63         << "Failed to initialize engine.";
64
65     // Wait for warmup to complete.
66     while (engine->getKVBucket()->isWarmingUp()) {
67         usleep(10);
68     }
69
70     // Once warmup is complete, set VB to active.
71     engine->setVBucketState(vbid, vbucket_state_active, false);
72 }
73
74 void EventuallyPersistentEngineTest::TearDown() {
75     // Need to force the destroy (i.e. pass true) because
76     // NonIO threads may have been disabled (see DCPTest subclass).
77     engine_v1->destroy(handle, true);
78     destroy_mock_event_callbacks();
79     destroy_engine();
80     // Cleanup any files we created.
81     cb::io::rmrf(test_dbname);
82 }
83
84 void EventuallyPersistentEngineTest::store_item(uint16_t vbid,
85                                                 const std::string& key,
86                                                 const std::string& value) {
87     Item item(makeStoredDocKey(key), /*flags*/0, /*exp*/0, value.c_str(),
88               value.size(), nullptr/*extmeta*/, 0/*extlen*/, 0/*cas*/,
89               -1/*seqno*/, vbid);
90     uint64_t cas;
91     EXPECT_EQ(ENGINE_SUCCESS,
92               engine->store(NULL, &item, &cas, OPERATION_SET));
93 }
94
95 const char EventuallyPersistentEngineTest::test_dbname[] = "ep_engine_ep_unit_tests_db";
96
97
98 TEST_P(SetParamTest, requirements_bucket_type) {
99     std::string bucketType = engine->getConfiguration().getBucketType();
100
101     struct value_t {
102         std::string param;
103         std::string value;
104         std::string bucketType;
105     };
106
107     std::vector<value_t> values{
108             // Parameter, Example value, applicable bucket
109             {"access_scanner_enabled", "true", "persistent"},
110             {"alog_sleep_time", "1441", "persistent"},
111             {"alog_task_time", "3", "persistent"},
112             {"ephemeral_full_policy", "auto_delete", "ephemeral"},
113     };
114
115     std::string msg;
116
117     for (auto v : values) {
118         auto ret = engine->setFlushParam(v.param.c_str(), v.value.c_str(), msg);
119         if (bucketType == v.bucketType) {
120             EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, ret)
121                     << "Parameter " << v.param
122                     << "could not be set on bucket type \"" << bucketType
123                     << "\"";
124         } else {
125             EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, ret)
126                     << "Setting parameter " << v.param
127                     << "should be invalid for bucket type \"" << bucketType
128                     << "\"";
129         }
130     }
131 }
132
133 TEST_F(EventuallyPersistentEngineTest, requirements_tap) {
134     Configuration& config = engine->getConfiguration();
135     config.setTap(true);
136
137     std::string msg;
138
139     EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
140               engine->setTapParam("tap_keepalive", "0", msg))
141             << "tap is enabled but \"tap_keepalive\" could not be set";
142
143     config.setTap(false);
144
145     EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
146               engine->setTapParam("tap_keepalive", "0", msg))
147             << "Setting \"tap_keepalive\" should be invalid if tap is disabled";
148 }
149
150 // Test cases which run for persistent and ephemeral buckets
151 INSTANTIATE_TEST_CASE_P(EphemeralOrPersistent,
152                         SetParamTest,
153                         ::testing::Values("persistent", "ephemeral"),
154                         [](const ::testing::TestParamInfo<std::string>& info) {
155                             return info.param;
156                         });