Refine FileLocker and add unittests 65/308065/1
authorYonggoo Kang <ygace.kang@samsung.com>
Fri, 15 Mar 2024 12:19:34 +0000 (21:19 +0900)
committerYonggoo Kang <ygace.kang@samsung.com>
Fri, 15 Mar 2024 12:19:39 +0000 (21:19 +0900)
- Move Exception for FileLocker to exception.h
- Add lockFile parameter into constructor of ServiceFileLocker
- Change throwing exception to logging error
- Add unittests for FileLocker
- Move the FILE_LOCKER to header

Change-Id: I4c7883d1558e20d2d63c05732a4d2feb4810d3d3

srcs/common/exception.h
srcs/common/file-lock.cpp
srcs/common/file-lock.h
srcs/common/service-file-locker.cpp
srcs/common/service-file-locker.h
srcs/common/utils.h
srcs/server/main.cpp
tests/CMakeLists.txt
tests/file-lock-test.cpp [new file with mode: 0644]

index 226b3edea34ac3442a4150f9581b173f0c26dfbd..dc6955105036a3fa899ebd32f5b5059cecae8e6e 100644 (file)
@@ -387,4 +387,10 @@ public:
     DECLARE_EXCEPTION_TYPE(Base, InvalidParameter)
 };
 
+class FileLockerException {
+public:
+    DECLARE_EXCEPTION_TYPE(WA::Exception, Base)
+    DECLARE_EXCEPTION_TYPE(Base, LockFailed)
+};
+
 } // namespace WebAuthn
index 7c071149b5669ab1a78276f3141ff1f9d35276b1..0f910ae2c5ace41cd80f47738c2b0d4ee06a1a41 100644 (file)
@@ -40,13 +40,13 @@ FileLocker::FileLocker(const std::string &lockFile, bool blocking)
 {
     if (lockFile.empty()) {
         LogError("File name can not be empty.");
-        ThrowMsg(FileLocker::Exception::LockFailed,
+        ThrowMsg(FileLockerException::LockFailed,
                  "File name can not be empty.");
     }
     m_lockFileFd = open(lockFile.c_str(), O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
     if (m_lockFileFd == -1) {
         LogError("Lock file cannot be opened " << lockFile);
-        ThrowMsg(FileLocker::Exception::LockFailed,
+        ThrowMsg(FileLockerException::LockFailed,
                  "Lock file cannot be opened " << lockFile);
     }
     m_locked = false;
@@ -57,11 +57,7 @@ FileLocker::FileLocker(const std::string &lockFile, bool blocking)
 
 FileLocker::~FileLocker()
 {
-    try {
-        Unlock();
-    } catch (...) {
-        LogError("~FileLocker() threw an exception");
-    }
+    Unlock();
     (void)close(m_lockFileFd);
 }
 
@@ -80,7 +76,7 @@ void FileLocker::Lock()
     m_locked = ret == 0;
     int err = errno;
     if (ret && err != EWOULDBLOCK)
-        LogAndThrowWithErrno(err, FileLocker::Exception::LockFailed, "locking a file " << m_lockFile);
+        LogErrno("locking a file " << m_lockFile);
 
     if (m_locked)
         LogDebug("We have a lock on " << m_lockFile << " file.");
@@ -94,7 +90,7 @@ void FileLocker::Unlock()
         int ret;
         while ((ret = flock(m_lockFileFd, LOCK_UN)) && (errno == EINTR));
         if (ret)
-            LogAndThrowErrno(FileLocker::Exception::UnlockFailed, "unlocking a file " << m_lockFile);
+            LogErrno("unlocking a file " << m_lockFile);
 
         m_locked = false;
         LogDebug("Lock released.");
index d019d9d53dcba1207a955f45804515863e4208b8..31a9a29b75941aa01582f5cb0b819eb0a93e3efa 100644 (file)
@@ -34,14 +34,6 @@ namespace WA {
 class FileLocker
 {
 public:
-    class Exception
-    {
-    public:
-        DECLARE_EXCEPTION_TYPE(WA::Exception, Base)
-        DECLARE_EXCEPTION_TYPE(Base, LockFailed)
-        DECLARE_EXCEPTION_TYPE(Base, UnlockFailed)
-    };
-
     FileLocker(const std::string &lockFile, bool blocking = false);
     virtual ~FileLocker();
 
index cdeb7c6baf5a8a4220923ce0e464c6cf1d47cdd9..e5c75765e4f0e1fef13361dc178278fbf38de7b6 100644 (file)
  */
 #include <service-file-locker.h>
 
-#define LOCKER_PATH_PREFIX "/run/"
-inline constexpr auto FILE_LOCKER = LOCKER_PATH_PREFIX "webauthn.lock";
-
 namespace WA {
 
-ServiceFileLocker::ServiceFileLocker(bool blocking) :
-        FileLocker(FILE_LOCKER, blocking) {}
+ServiceFileLocker::ServiceFileLocker(const std::string &lockFile, bool blocking) :
+        FileLocker(lockFile, blocking) {}
 
 } /* namespace WebAuthn */
index 0fd16cf98030c7c819b51c6201f8459565540707..364233ac1b36a771ce8cee80801c99b208a9bcf8 100644 (file)
 #pragma once
 
 #include <file-lock.h>
+#define LOCKER_PATH_PREFIX "/run/"
+inline constexpr auto FILE_LOCKER = LOCKER_PATH_PREFIX "webauthn.lock";
 
 namespace WA {
 
 class ServiceFileLocker: public FileLocker
 {
 public:
-    explicit ServiceFileLocker(bool blocking = false);
+    explicit ServiceFileLocker(const std::string &lockFile,
+        bool blocking = false);
 };
 
 } /* namespace WebAuthn */
index 15e00e42d0952cf08f6f8fb293177f9ef4e1c96e..d3f0aff8b043dfb62cbaf08a32fdf560774469b4 100644 (file)
@@ -62,6 +62,10 @@ int try_catch(F &&f) {
         LogError("WA::ServiceException::InActive: " << e.DumpToString());
         std::cerr << "WA::ServiceException::InActive: " << e.DumpToString() << std::endl;
         return WAUTHN_ERROR_SOCKET;
+    } catch (const FileLockerException::LockFailed &e) {
+        LogError("WA::FileLockerException::LockFailed: " << e.DumpToString());
+        std::cerr << "WA::FileLockerException::LockFailed: " << e.DumpToString() << std::endl;
+        return WAUTHN_ERROR_INVALID_STATE;
     } catch (const std::logic_error &e) {
         LogError("Invalid logic: " << e.what());
         std::cerr << "Invalid logic: " << e.what() << std::endl;
index 8223a0b2b17d9a25961a0b6069677bebacf3dce7..be2d760d657f8fb8b4751447ffef224976a9002e 100644 (file)
@@ -59,7 +59,7 @@ int main(void)
     UNHANDLED_EXCEPTION_HANDLER_BEGIN
     {
         WA::Singleton<WA::WebAuthnLog>::Instance().SetTag(WEBAUTHN_LOG_TAG);
-        WA::ServiceFileLocker serviceLock(true);
+        WA::ServiceFileLocker serviceLock(FILE_LOCKER, true);
         sigset_t mask;
         sigemptyset(&mask);
         sigaddset(&mask, SIGTERM);
index bb14e0d1a929733c69aef7c704cf72eb0ca435b1..4a9976b0907a858f61697216fc189eb318764df9 100644 (file)
@@ -7,6 +7,7 @@ PKG_CHECK_MODULES(UNIT_TESTS_DEPS
 SET(UNIT_TESTS_SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/unittests.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/webauthn-client-test.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/file-lock-test.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/serialization-test.cpp
 )
 
diff --git a/tests/file-lock-test.cpp b/tests/file-lock-test.cpp
new file mode 100644 (file)
index 0000000..6cadfcb
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ *
+ * @file        dl-loader-test.cpp
+ * @version     1.0
+ * @brief       unit tests for dl-loader
+ */
+
+#include <file-lock.h>
+#include <gtest/gtest.h>
+#include <iostream>
+
+namespace WA {
+
+class FileLockerTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        // Do initialization if needed.
+    }
+
+    void TearDown() override {
+        // Do deinitialization if needed.
+    }
+};
+
+TEST_F(FileLockerTest, lock_and_unlock_P)
+{
+    int ret = 0;
+    try{
+        FileLocker fileLocker("/tmp/.webauthn-test.lock", true);
+        EXPECT_EQ(fileLocker.Locked(), true);
+        fileLocker.Unlock();
+        EXPECT_EQ(fileLocker.Locked(), false);
+    } catch (...)
+    {
+        std::cout << "Error in FileLocker" << std::endl;
+        ret = -1;
+    }
+    EXPECT_EQ(ret, 0);
+}
+
+TEST_F(FileLockerTest, lock_after_unlock_P)
+{
+    int ret = 0;
+    try{
+        FileLocker fileLocker("/tmp/.webauthn-test.lock", true);
+        EXPECT_EQ(fileLocker.Locked(), true);
+        fileLocker.Unlock();
+        EXPECT_EQ(fileLocker.Locked(), false);
+        FileLocker fileLocker2("/tmp/.webauthn-test.lock", true);
+        EXPECT_EQ(fileLocker2.Locked(), true);
+        fileLocker2.Unlock();
+        EXPECT_EQ(fileLocker2.Locked(), false);
+    } catch (...)
+    {
+        std::cout << "Error in FileLocker" << std::endl;
+        ret = -1;
+    }
+    EXPECT_EQ(ret, 0);
+}
+
+TEST_F(FileLockerTest, lock_empty_path_N)
+{
+    int ret = 0;
+    try{
+        FileLocker fileLocker("", true);
+    } catch (FileLockerException::LockFailed &e)
+    {
+        ret = 1;
+    } catch (...)
+    {
+        std::cout << "Error in FileLocker" << std::endl;
+        ret = -1;
+    }
+    EXPECT_EQ(ret, 1);
+}
+
+TEST_F(FileLockerTest, lock_invalid_path_N)
+{
+    int ret = 0;
+    try{
+        FileLocker fileLocker("/invalidpath/webauthn-test.lock", true);
+    } catch (FileLockerException::LockFailed &e)
+    {
+        ret = 1;
+    } catch (...)
+    {
+        std::cout << "Error in FileLocker" << std::endl;
+        ret = -1;
+    }
+    EXPECT_EQ(ret, 1);
+}
+
+TEST_F(FileLockerTest, lock_to_locked_path_N)
+{
+    int ret = 0;
+    try{
+        FileLocker fileLocker("/tmp/.webauthn-test.lock", true);
+        FileLocker fileLocker2("/tmp/.webauthn-test.lock", false);
+        EXPECT_EQ(fileLocker.Locked(), true);
+        EXPECT_EQ(fileLocker2.Locked(), false);
+        fileLocker.Unlock();
+        EXPECT_EQ(fileLocker.Locked(), false);
+    } catch (FileLockerException::LockFailed &e)
+    {
+        ret = 1;
+    } catch (...)
+    {
+        std::cout << "Error in FileLocker" << std::endl;
+        ret = -1;
+    }
+    EXPECT_EQ(ret, 0);
+}
+
+} // namespace WebAuthn