Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Os::FileSystem and Os::Directory #2871

Merged
merged 45 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
bf11671
Add FileSystem Interface
thomas-bc Aug 16, 2024
c70ced0
Add OS::FileSystem interface and implementations
thomas-bc Aug 16, 2024
eea790f
static interface + global Os::init()
thomas-bc Aug 20, 2024
34c9f38
Add test harness
thomas-bc Aug 20, 2024
2cdca89
Implement Os::Directory interfaces and use it in FileSystem::readDire…
thomas-bc Aug 20, 2024
e1bce3c
Add Stub tests for Directory and FileSystem
thomas-bc Aug 22, 2024
12a655a
wip: modify the interface from Michael feedback
thomas-bc Aug 29, 2024
8e11926
wip: move functions around and rework interface a little more
thomas-bc Aug 30, 2024
8b6899a
Add Directory rule-based tests
thomas-bc Aug 30, 2024
af0223a
Refactored Directory for open-create + WIP: FileSystem tests
thomas-bc Sep 9, 2024
645a771
Update state tracking mechanism in FileSystem test implementation + a…
thomas-bc Sep 10, 2024
8f2c5ba
Replace bounded while-loop with for-loop
thomas-bc Sep 10, 2024
e7e8383
Code cleanup
thomas-bc Sep 10, 2024
d89a27f
fix typo
thomas-bc Sep 10, 2024
a25d748
Rename FileTracker and code reorganization / clarification
thomas-bc Sep 11, 2024
96894f1
Code style and add CWD rule
thomas-bc Sep 11, 2024
709b4ff
Clean up tester code
thomas-bc Sep 12, 2024
1b4afc0
More cleanup
thomas-bc Sep 12, 2024
5f9da79
Add Posix tests to Os_ut_exe
thomas-bc Sep 12, 2024
7ae9db4
Fix DpCatalog readDirectory usage
thomas-bc Sep 13, 2024
dd29323
Appease CI checks
thomas-bc Sep 13, 2024
3929031
Spelling and CI warnings
thomas-bc Sep 13, 2024
930aa97
Spelling + removing FppConstants include
thomas-bc Sep 13, 2024
a0aba85
Add review changes and todos
thomas-bc Sep 16, 2024
aa5592b
Add Directory::read(Fw::StringBase&) overload
thomas-bc Sep 16, 2024
520beb6
Refactor copyFileData to iterate over copied size
thomas-bc Sep 17, 2024
ae7edf2
Remove FppConstants.hpp include
thomas-bc Sep 17, 2024
815a27a
Rework moveFile into rename/copy-remove
thomas-bc Sep 17, 2024
7f54573
Add majestic comments
thomas-bc Sep 17, 2024
d2c2e59
Add option to error if dir exist in Fs::createDirectory
thomas-bc Sep 18, 2024
32be989
spelling
thomas-bc Sep 18, 2024
eef6499
include <algorithm> for std::find in tests
thomas-bc Sep 18, 2024
2518010
Fix leftover ::CREATE modes in comments and stub tests
thomas-bc Sep 18, 2024
f202ec4
Fix CmdSequencer test case
thomas-bc Sep 18, 2024
ac14b33
Fix memory leak in testing by conditioning the Open rule
thomas-bc Sep 18, 2024
d62b5d6
Fix FileManager tests
thomas-bc Sep 18, 2024
c8eed05
Add Directory and FileSystem FPP type definitions; update CMakeLists …
thomas-bc Sep 18, 2024
f83d57f
spelling
thomas-bc Sep 18, 2024
6aa7b75
Reoder header guards
thomas-bc Sep 19, 2024
6301a45
Implement changes from peer-review
thomas-bc Sep 26, 2024
fe1efa9
read into StringBase with const_cast
thomas-bc Sep 26, 2024
96cda71
Fix resetSer() call
thomas-bc Sep 26, 2024
6da1d39
Fix spelling
thomas-bc Sep 26, 2024
63f9955
fix spelling again i guess
thomas-bc Sep 26, 2024
9c348b3
Fix DpCatalog unchecked return value
thomas-bc Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .github/actions/spelling/line_forbidden.patterns
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
# s.b. anymore
\bany more[,.]

# s.b. cannot
\b[Cc]an not\b

# s.b. GitHub
(?<![&*.]|// |\btype )\bGithub\b(?![{)])

Expand Down Expand Up @@ -70,16 +67,9 @@
# s.b. or (more|less)
\bore (?:more|less)\b

# s.b. nonexistent
\bnon existing\b
\b[Nn]o[nt][- ]existent\b

# s.b. brief / details/ param / return / retval
(?:^\s*|(?:\*|//|/*)\s+`)[\\@](?:breif|(?:detail|detials)|(?:params(?!\.)|prama?)|ret(?:uns?)|retvl)\b

# s.b. preexisting
[Pp]re[- ]existing

# s.b. preempt
[Pp]re[- ]empt\b

Expand Down
2 changes: 1 addition & 1 deletion Fw/Types/StringBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class StringBase : public Serializable {
virtual SizeType getCapacity() const = 0; //!< return size of buffer
SizeType length() const; //!< Get length of string

//! Get the maximum length of a string that the buffer can hold
//! Get the maximum length of a string that the buffer can hold (which is capacity - 1)
SizeType maxLength() const;
//! Get the static serialized size of a string
//! This is the max length of the string plus the size of the stored size
Expand Down
24 changes: 16 additions & 8 deletions Os/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/ValidatedFile.cpp"

# Refactored common files
"${CMAKE_CURRENT_LIST_DIR}/Os.cpp"
"${CMAKE_CURRENT_LIST_DIR}/File.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Task.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Mutex.cpp"
"${CMAKE_CURRENT_LIST_DIR}/FileSystem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Directory.cpp"
)
# Check for default logger
if (NOT FPRIME_DISABLE_DEFAULT_LOGGER)
Expand All @@ -56,8 +59,6 @@ if (FPRIME_USE_POSIX)
"${CMAKE_CURRENT_LIST_DIR}/Linux/InterruptLock.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Linux/WatchdogTimer.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Posix/IntervalTimer.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Linux/FileSystem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Linux/Directory.cpp"
)
endif()
# Darwin IPC queue implementation
Expand Down Expand Up @@ -97,26 +98,33 @@ endif()
register_fprime_module()

require_fprime_implementation(Os/File)
require_fprime_implementation(Os/FileSystem)
require_fprime_implementation(Os/Directory)
require_fprime_implementation(Os/Mutex)
# require_fprime_implementation(Os/Task) # should be added in
require_fprime_implementation(Os/Mutex)
# require_fprime_implementation(Os/Console) # should be added in


### UTS ### Note: 3 separate UTs registered here.
set(UT_SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/test/ut/OsQueueTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/OsTestMain.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/IntervalTimerTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/OsFileSystemTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/OsValidateFileTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/OsSystemResourcesTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/OsMutexBasicLockableTest.cpp"
)
register_fprime_ut()
if (BUILD_TESTING)
foreach (TEST IN ITEMS StubFileTest PosixFileTest StubMutexTest PosixMutexTest) # add? : StubTaskTest PosixTaskTest
if (TARGET "${TEST}")
add_dependencies("Os_ut_exe" "${TEST}")
endif()
foreach (TEST IN ITEMS
thomas-bc marked this conversation as resolved.
Show resolved Hide resolved
StubFileTest PosixFileTest
StubMutexTest PosixMutexTest
StubDirectoryTest PosixDirectory
StubFileSystemTest PosixFileSystemTest
) # add? : StubTaskTest PosixTaskTest
if (TARGET "${TEST}")
add_dependencies("Os_ut_exe" "${TEST}")
endif()
endforeach()
endif()
# Second UT Pthreads
Expand Down
148 changes: 148 additions & 0 deletions Os/Directory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// ======================================================================
// \title Os/Directory.cpp
// \brief common function implementation for Os::Directory
// ======================================================================
#include <Fw/Types/Assert.hpp>
#include <Os/Directory.hpp>

namespace Os {

Directory::Directory() : m_is_open(false), m_handle_storage(), m_delegate(*DirectoryInterface::getDelegate(m_handle_storage)) {
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
}

Directory::~Directory() {
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
if (this->m_is_open) {
this->close();
}
this->m_delegate.~DirectoryInterface();
}

// ------------------------------------------------------------
// Directory operations delegating to implementation
// ------------------------------------------------------------
DirectoryHandle* Directory::getHandle() {
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
return this->m_delegate.getHandle();
}

Directory::Status Directory::open(const char* path, OpenMode mode) {

Check notice

Code scanning / CodeQL

Use of basic integral type Note

path uses the basic integral type char rather than a typedef with size and signedness.
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
FW_ASSERT(path != nullptr);
FW_ASSERT(mode >= 0 and mode < OpenMode::MAX_OPEN_MODE);
Status status = this->m_delegate.open(path, mode);
if (status == Status::OP_OK) {
this->m_is_open = true;
}
return status;
}

bool Directory::isOpen() {

Check notice

Code scanning / CodeQL

Use of basic integral type Note

isOpen uses the basic integral type bool rather than a typedef with size and signedness.
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
return this->m_is_open;
}
Directory::Status Directory::rewind() {
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
if (not this->m_is_open) {
return Status::NOT_OPENED;
}
return this->m_delegate.rewind();
}

Directory::Status Directory::read(char * fileNameBuffer, FwSizeType bufSize) {

Check notice

Code scanning / CodeQL

Use of basic integral type Note

fileNameBuffer uses the basic integral type char rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

Use of basic integral type Note

bufSize uses the basic integral type unsigned long rather than a typedef with size and signedness.
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
if (not this->m_is_open) {
return Status::NOT_OPENED;
}
FW_ASSERT(fileNameBuffer != nullptr);
Status status = this->m_delegate.read(fileNameBuffer, bufSize);
Dismissed Show dismissed Hide dismissed
fileNameBuffer[bufSize - 1] = '\0'; // Guarantee null-termination
return status;
}

Directory::Status Directory::read(Fw::StringBase& filename) {
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
if (not this->m_is_open) {
return Status::NOT_OPENED;
}
return this->m_delegate.read(const_cast<char*>(filename.toChar()), filename.getCapacity());
Dismissed Show dismissed Hide dismissed
}

void Directory::close() {
FW_ASSERT(&this->m_delegate == reinterpret_cast<DirectoryInterface*>(&this->m_handle_storage[0]));
this->m_is_open = false;
return this->m_delegate.close();
}

// ------------------------------------------------------------
// Common functions built on top of OS-specific functions
// ------------------------------------------------------------

Directory::Status Directory::getFileCount(FwSizeType& fileCount) {

Check notice

Code scanning / CodeQL

Use of basic integral type Note

fileCount uses the basic integral type unsigned long rather than a typedef with size and signedness.
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
Dismissed Show dismissed Hide dismissed
if (not this->m_is_open) {
return Status::NOT_OPENED;
}
// Rewind to ensure we start from the beginning of the stream
if (this->rewind() != Status::OP_OK) {
return Status::OTHER_ERROR;
}
const FwSizeType loopLimit = std::numeric_limits<FwSizeType>::max();

Check notice

Code scanning / CodeQL

Use of basic integral type Note

loopLimit uses the basic integral type unsigned long rather than a typedef with size and signedness.
FwSizeType count = 0;

Check notice

Code scanning / CodeQL

Use of basic integral type Note

count uses the basic integral type unsigned long rather than a typedef with size and signedness.
char unusedBuffer[1]; // buffer must have size but is unused

Check notice

Code scanning / CodeQL

Use of basic integral type Note

unusedBuffer uses the basic integral type char rather than a typedef with size and signedness.
Status readStatus = Status::OP_OK;
fileCount = 0;

Check warning

Code scanning / CodeQL

Unchecked function argument Warning

This use of parameter fileCount has not been checked.
// Count files by reading each file entry until there is NO_MORE_FILES
for (FwSizeType iter = 0; iter < loopLimit; ++iter) {

Check notice

Code scanning / CodeQL

Use of basic integral type Note

iter uses the basic integral type unsigned long rather than a typedef with size and signedness.
readStatus = this->read(unusedBuffer, sizeof(unusedBuffer));
if (readStatus == Status::NO_MORE_FILES) {
break;
} else if (readStatus != Status::OP_OK) {
return Status::OTHER_ERROR;
}
count++;
}
fileCount = count;
if (this->rewind() != Status::OP_OK) {
return Status::OTHER_ERROR;
}
return Status::OP_OK;
}


Directory::Status Directory::readDirectory(Fw::String filenameArray[], const FwSizeType filenameArraySize, FwSizeType& filenameCount) {

Check notice

Code scanning / CodeQL

Use of basic integral type Note

filenameArraySize uses the basic integral type unsigned long rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

Use of basic integral type Note

filenameCount uses the basic integral type unsigned long rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

Long function without assertion Note

All functions of more than 10 lines should have at least one assertion.

Check notice

Code scanning / CodeQL

No raw arrays in interfaces Note

Raw arrays should not be used in interfaces. A container class should be used instead.
FW_ASSERT(filenameArray != nullptr);
FW_ASSERT(filenameArraySize > 0);
if (not this->m_is_open) {
return Status::NOT_OPENED;
}
// Rewind to ensure we start reading from the beginning of the stream
if (this->rewind() != Status::OP_OK) {
return Status::OTHER_ERROR;
}

Status readStatus = Status::OP_OK;
Status returnStatus = Status::OP_OK;
FwSizeType index;

Check notice

Code scanning / CodeQL

Use of basic integral type Note

index uses the basic integral type unsigned long rather than a typedef with size and signedness.
filenameCount = 0;

Check warning

Code scanning / CodeQL

Unchecked function argument Warning

This use of parameter filenameCount has not been checked.
// Iterate through the directory and read the filenames into the array
for (index = 0; index < filenameArraySize; index++) {
readStatus = this->read(filenameArray[index]);
if (readStatus == Status::NO_MORE_FILES) {
break;
} else if (readStatus != Status::OP_OK) {
return Status::OTHER_ERROR;
}
}
filenameCount = index;

if (this->rewind() != Status::OP_OK) {
return Status::OTHER_ERROR;
}

return returnStatus;

}


} // namespace Os
Loading
Loading