Skip to content

Commit d6aeca3

Browse files
committed
Add OLP_SDK_USE_STD_ANY handling and test cases
* Add handling of the OLP_SDK_USE_STD_ANY in CMakeFile to propagate it durintg the build. * Add one additional test case and new test for olp::porting::any to improve code coverage. Relates-To: NLAM-157 Signed-off-by: Khomenko Denys <[email protected]>
1 parent 44008f2 commit d6aeca3

File tree

6 files changed

+219
-15
lines changed

6 files changed

+219
-15
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ option(OLP_SDK_ENABLE_TESTING "Flag to enable/disable building unit and integrat
3838
option(OLP_SDK_BUILD_DOC "Build SDK documentation" OFF)
3939
option(OLP_SDK_NO_EXCEPTION "Disable exception handling" OFF)
4040
option(OLP_SDK_USE_STD_OPTIONAL "Use std::optional instead of boost::optional with C++17 and above" OFF)
41+
option(OLP_SDK_USE_STD_ANY "Use std::any instead of boost::any with C++17 and above" OFF)
4142
option(OLP_SDK_BOOST_THROW_EXCEPTION_EXTERNAL "The boost::throw_exception() is defined externally" OFF)
4243
option(OLP_SDK_BUILD_EXTERNAL_DEPS "Download and build external dependencies" ON)
4344
option(OLP_SDK_BUILD_EXAMPLES "Enable examples targets" OFF)

docs/get-started.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ cmake --build . --target docs
131131
| `OLP_SDK_BUILD_EXTERNAL_DEPS` | Defaults to `ON`. If enabled, CMake downloads and compiles dependencies. |
132132
| `OLP_SDK_NO_EXCEPTION` | Defaults to `OFF`. If enabled, all libraries are built without exceptions. |
133133
| `OLP_SDK_USE_STD_OPTIONAL` | Defaults to `OFF`. If enabled, all libraries are built with std::optional type instead of boost::optional for C++17 and above. |
134+
| `OLP_SDK_USE_STD_ANY` | Defaults to `OFF`. If enabled, all libraries are built with std::any type instead of boost::any for C++17 and above. |
134135
| `OLP_SDK_BOOST_THROW_EXCEPTION_EXTERNAL` | Defaults to `OFF`. When `OLP_SDK_NO_EXCEPTION` is `ON`, `boost` requires `boost::throw_exception()` to be defined. If enabled, the external definition of `boost::throw_exception()` is used. Otherwise, the library uses own definition. |
135136
| `OLP_SDK_MSVC_PARALLEL_BUILD_ENABLE` (Windows Only) | Defaults to `ON`. If enabled, the `/MP` compilation flag is added to build the Data SDK using multiple cores. |
136137
| `OLP_SDK_DISABLE_DEBUG_LOGGING`| Defaults to `OFF`. If enabled, the debug and trace level log messages are not printed. |

olp-cpp-sdk-core/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@ if (OLP_SDK_USE_STD_OPTIONAL)
451451
PUBLIC OLP_CPP_SDK_USE_STD_OPTIONAL)
452452
endif()
453453

454+
if (OLP_SDK_USE_STD_ANY)
455+
target_compile_definitions(${PROJECT_NAME}
456+
PUBLIC OLP_SDK_USE_STD_ANY)
457+
endif()
458+
454459
target_include_directories(${PROJECT_NAME} PUBLIC
455460
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
456461
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>

olp-cpp-sdk-core/tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ set(OLP_CPP_SDK_CORE_TESTS_SOURCES
6161
./logging/MessageFormatterTest.cpp
6262
./logging/MockAppender.cpp
6363

64+
./porting/AnyTest.cpp
65+
6466
./thread/ContinuationTest.cpp
6567
./thread/ExecutionContextTest.cpp
6668
./thread/PriorityQueueExtendedTest.cpp

olp-cpp-sdk-core/tests/cache/DefaultCacheImplTest.cpp

Lines changed: 113 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
* License-Filename: LICENSE
1818
*/
1919

20+
#include <dirent.h>
2021
#include <chrono>
22+
#include <fstream>
2123
#include <thread>
2224

2325
#include <gtest/gtest.h>
@@ -31,6 +33,9 @@
3133
#define WIN32_LEAN_AND_MEAN
3234
#include <Windows.h>
3335
#undef max
36+
#else
37+
#include <sys/stat.h>
38+
#include <sys/types.h>
3439
#endif
3540

3641
#include "Helpers.h"
@@ -1399,21 +1404,23 @@ class DefaultCacheImplOpenTest
13991404
public testing::WithParamInterface<OpenTestParameters> {};
14001405

14011406
TEST_P(DefaultCacheImplOpenTest, ReadOnlyDir) {
1402-
const auto setup_dir = [&](const olp::porting::optional<std::string>& cache_path) {
1403-
if (cache_path) {
1404-
if (olp::utils::Dir::Exists(*cache_path)) {
1405-
ASSERT_TRUE(olp::utils::Dir::Remove(*cache_path));
1406-
}
1407-
ASSERT_TRUE(olp::utils::Dir::Create(*cache_path));
1408-
ASSERT_TRUE(SetRights(*cache_path, true));
1409-
}
1410-
};
1411-
1412-
const auto reset_dir = [&](const olp::porting::optional<std::string>& cache_path) {
1413-
if (cache_path) {
1414-
ASSERT_TRUE(olp::utils::Dir::Remove(*cache_path));
1415-
}
1416-
};
1407+
const auto setup_dir =
1408+
[&](const olp::porting::optional<std::string>& cache_path) {
1409+
if (cache_path) {
1410+
if (olp::utils::Dir::Exists(*cache_path)) {
1411+
ASSERT_TRUE(olp::utils::Dir::Remove(*cache_path));
1412+
}
1413+
ASSERT_TRUE(olp::utils::Dir::Create(*cache_path));
1414+
ASSERT_TRUE(SetRights(*cache_path, true));
1415+
}
1416+
};
1417+
1418+
const auto reset_dir =
1419+
[&](const olp::porting::optional<std::string>& cache_path) {
1420+
if (cache_path) {
1421+
ASSERT_TRUE(olp::utils::Dir::Remove(*cache_path));
1422+
}
1423+
};
14171424

14181425
const OpenTestParameters test_params = GetParam();
14191426

@@ -1447,4 +1454,95 @@ std::vector<OpenTestParameters> DefaultCacheImplOpenParams() {
14471454
INSTANTIATE_TEST_SUITE_P(, DefaultCacheImplOpenTest,
14481455
testing::ValuesIn(DefaultCacheImplOpenParams()));
14491456

1457+
TEST_F(DefaultCacheImplTest, ProtectedCacheIOErrorFallbackToReadOnly) {
1458+
SCOPED_TRACE("IOError fallback to read-only for protected cache");
1459+
1460+
const std::string ioerror_path =
1461+
olp::utils::Dir::TempDirectory() + "/unittest_ioerror_fallback";
1462+
1463+
if (olp::utils::Dir::Exists(ioerror_path)) {
1464+
helpers::MakeDirectoryAndContentReadonly(ioerror_path, false);
1465+
ASSERT_TRUE(olp::utils::Dir::Remove(ioerror_path));
1466+
}
1467+
1468+
ASSERT_TRUE(olp::utils::Dir::Create(ioerror_path));
1469+
1470+
{
1471+
cache::CacheSettings temp_settings;
1472+
temp_settings.disk_path_protected = ioerror_path;
1473+
DefaultCacheImplHelper temp_cache(temp_settings);
1474+
ASSERT_EQ(temp_cache.Open(),
1475+
cache::DefaultCache::StorageOpenResult::Success);
1476+
temp_cache.Close();
1477+
}
1478+
1479+
// Make all the database files read-only, but keep directory writable.
1480+
// This way Dir::IsReadOnly(directory) returns false (directory is writable),
1481+
// but LevelDB gets IOError when trying to write to the read-only DB files.
1482+
#ifndef _WIN32
1483+
DIR* dir = opendir(ioerror_path.c_str());
1484+
ASSERT_TRUE(dir != nullptr);
1485+
struct dirent* entry;
1486+
while ((entry = readdir(dir)) != nullptr) {
1487+
if (entry->d_type == DT_REG) {
1488+
std::string file_path = ioerror_path + "/" + entry->d_name;
1489+
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
1490+
continue;
1491+
ASSERT_EQ(chmod(file_path.c_str(), S_IRUSR | S_IRGRP | S_IROTH), 0);
1492+
}
1493+
}
1494+
closedir(dir);
1495+
1496+
chmod(ioerror_path.c_str(),
1497+
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
1498+
#else
1499+
WIN32_FIND_DATAA find_data;
1500+
HANDLE hFind = FindFirstFileA((ioerror_path + "\\*").c_str(), &find_data);
1501+
ASSERT_NE(hFind, INVALID_HANDLE_VALUE);
1502+
1503+
do {
1504+
if (strcmp(find_data.cFileName, ".") == 0 ||
1505+
strcmp(find_data.cFileName, "..") == 0) {
1506+
continue;
1507+
}
1508+
if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
1509+
// It's a file, make it read-only
1510+
std::string file_path = ioerror_path + "\\" + find_data.cFileName;
1511+
DWORD attrs = GetFileAttributesA(file_path.c_str());
1512+
ASSERT_NE(attrs, INVALID_FILE_ATTRIBUTES);
1513+
ASSERT_TRUE(SetFileAttributesA(file_path.c_str(),
1514+
attrs | FILE_ATTRIBUTE_READONLY));
1515+
}
1516+
} while (FindNextFileA(hFind, &find_data));
1517+
FindClose(hFind);
1518+
1519+
// Ensure directory itself is not read-only (keep it writable)
1520+
DWORD dir_attrs = GetFileAttributesA(ioerror_path.c_str());
1521+
ASSERT_NE(dir_attrs, INVALID_FILE_ATTRIBUTES);
1522+
if (dir_attrs & FILE_ATTRIBUTE_READONLY) {
1523+
ASSERT_TRUE(SetFileAttributesA(ioerror_path.c_str(),
1524+
dir_attrs & ~FILE_ATTRIBUTE_READONLY));
1525+
}
1526+
#endif
1527+
ASSERT_FALSE(olp::utils::Dir::IsReadOnly(ioerror_path));
1528+
1529+
cache::CacheSettings settings;
1530+
settings.disk_path_protected = ioerror_path;
1531+
settings.openOptions = cache::OpenOptions::Default;
1532+
DefaultCacheImplHelper cache(settings);
1533+
1534+
// Open should attempt R/W first, get IOError because files are read-only,
1535+
// then retry in read-only mode.
1536+
auto open_result = cache.Open();
1537+
EXPECT_TRUE(
1538+
open_result == cache::DefaultCache::StorageOpenResult::Success ||
1539+
open_result ==
1540+
cache::DefaultCache::StorageOpenResult::ProtectedCacheCorrupted ||
1541+
open_result ==
1542+
cache::DefaultCache::StorageOpenResult::OpenDiskPathFailure);
1543+
1544+
helpers::MakeDirectoryAndContentReadonly(ioerror_path, false);
1545+
ASSERT_TRUE(olp::utils::Dir::Remove(ioerror_path));
1546+
}
1547+
14501548
} // namespace
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (C) 2025 HERE Europe B.V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
#include <gtest/gtest.h>
21+
#include <olp/core/porting/any.h>
22+
#include <string>
23+
24+
TEST(AnyTest, AnyCastConstReference) {
25+
// Test any_cast with const reference (covers line 84 in any.h)
26+
const olp::porting::any const_any = std::string("test_value");
27+
28+
auto result = olp::porting::any_cast<std::string>(const_any);
29+
EXPECT_EQ("test_value", result);
30+
}
31+
32+
TEST(AnyTest, AnyCastNonConstReference) {
33+
// Test any_cast with non-const reference
34+
olp::porting::any any_obj = std::string("test_value");
35+
36+
auto result = olp::porting::any_cast<std::string>(any_obj);
37+
EXPECT_EQ("test_value", result);
38+
}
39+
40+
TEST(AnyTest, AnyCastRValueReference) {
41+
// Test any_cast with rvalue reference
42+
auto result = olp::porting::any_cast<std::string>(
43+
olp::porting::any(std::string("test_value")));
44+
EXPECT_EQ("test_value", result);
45+
}
46+
47+
TEST(AnyTest, AnyCastConstPointer) {
48+
// Test any_cast with const pointer
49+
const olp::porting::any any_obj = std::string("test_value");
50+
51+
const std::string* ptr = olp::porting::any_cast<std::string>(&any_obj);
52+
ASSERT_NE(nullptr, ptr);
53+
EXPECT_EQ("test_value", *ptr);
54+
}
55+
56+
TEST(AnyTest, AnyCastNonConstPointer) {
57+
// Test any_cast with non-const pointer
58+
olp::porting::any any_obj = std::string("test_value");
59+
60+
std::string* ptr = olp::porting::any_cast<std::string>(&any_obj);
61+
ASSERT_NE(nullptr, ptr);
62+
EXPECT_EQ("test_value", *ptr);
63+
}
64+
65+
TEST(AnyTest, HasValue) {
66+
// Test has_value function
67+
olp::porting::any empty_any;
68+
EXPECT_FALSE(olp::porting::has_value(empty_any));
69+
70+
olp::porting::any filled_any = std::string("test");
71+
EXPECT_TRUE(olp::porting::has_value(filled_any));
72+
}
73+
74+
TEST(AnyTest, Reset) {
75+
// Test reset function
76+
olp::porting::any any_obj = std::string("test_value");
77+
EXPECT_TRUE(olp::porting::has_value(any_obj));
78+
79+
olp::porting::reset(any_obj);
80+
EXPECT_FALSE(olp::porting::has_value(any_obj));
81+
}
82+
83+
TEST(AnyTest, MakeAny) {
84+
// Test make_any with variadic arguments
85+
auto any_obj = olp::porting::make_any<std::string>("test");
86+
auto result = olp::porting::any_cast<std::string>(any_obj);
87+
EXPECT_EQ("test", result);
88+
}
89+
90+
TEST(AnyTest, MakeAnyWithInitializerList) {
91+
// Test make_any with initializer list
92+
auto any_obj = olp::porting::make_any<std::vector<int>>({1, 2, 3, 4, 5});
93+
auto result = olp::porting::any_cast<std::vector<int>>(any_obj);
94+
EXPECT_EQ(5u, result.size());
95+
EXPECT_EQ(1, result[0]);
96+
EXPECT_EQ(5, result[4]);
97+
}

0 commit comments

Comments
 (0)