Compare commits
No commits in common. "d7cfa3f76c81750d80f5998a4b00bab4e01f053b" and "946f93eaca73a96d528a00ef7844852f88644a09" have entirely different histories.
d7cfa3f76c
...
946f93eaca
@ -1,11 +0,0 @@
|
|||||||
# Google style C++ Code Style settings
|
|
||||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
|
||||||
|
|
||||||
Language: Cpp
|
|
||||||
BasedOnStyle: Google
|
|
||||||
AccessModifierOffset: -1
|
|
||||||
AlignAfterOpenBracket: Align
|
|
||||||
AlignOperands: Align
|
|
||||||
AllowAllArgumentsOnNextLine: true
|
|
||||||
ColumnLimit: 80
|
|
||||||
BreakBeforeBraces: Allman
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,4 @@
|
|||||||
# ---> C++
|
# ---> C++
|
||||||
# build artifacts
|
|
||||||
build/
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
# Root cmake file sketch (might change it later)
|
|
||||||
# Author: Unai Blazquez
|
|
||||||
# License: GPL-3-or-later
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.16)
|
|
||||||
project(azkoyen_ipc_test LANGUAGES CXX)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
# Core library
|
|
||||||
add_library(core
|
|
||||||
src/core/SysfsRead.cxx
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
||||||
|
|
||||||
#tests
|
|
||||||
enable_testing()
|
|
||||||
add_subdirectory(tests)
|
|
||||||
22
README.md
22
README.md
@ -1,23 +1,3 @@
|
|||||||
# azkoyen_technical_test
|
# azkoyen_technical_test
|
||||||
|
|
||||||
Azkoyen technical test implementation. Implemented (mostly) on standard c++ 17 framework, but with Qt wherever was necessary.
|
Azkoyen technical test implementation. Implemented (mostly) on standard c++ 17 framework, but with Qt wherever was necessary
|
||||||
|
|
||||||
## Development approach
|
|
||||||
|
|
||||||
A Test-Driven Development (TDD) workflow was followed throughout the project. Every component — from the lowest-level file reader to the GUI window — has a corresponding Google Test suite that was written before (or alongside) the production code. This ensures each module behaves correctly in isolation and makes regressions immediately visible.
|
|
||||||
|
|
||||||
## SysfsRead class
|
|
||||||
|
|
||||||
`SysfsReader` ([include/SysfsRead.hpp](include/SysfsRead.hpp), [src/core/SysfsRead.cxx](src/core/SysfsRead.cxx)) is the lowest-level component. It opens a sysfs-like file and translates its raw text content into a `SysfsStatus` enum:
|
|
||||||
|
|
||||||
| File content | Status |
|
|
||||||
|--------------------------|---------------------|
|
|
||||||
| `"1"` | `Enabled` |
|
|
||||||
| `"error: temp too high"` | `ErrorTempTooHigh` |
|
|
||||||
| empty / whitespace-only | `Empty` |
|
|
||||||
| file missing | `Unreachable` |
|
|
||||||
| anything else | `UnexpectedValue` |
|
|
||||||
|
|
||||||
The reader never throws on I/O errors; every outcome is expressed through the enum so callers can react without exception handling. A helper `trim_in_place` strips trailing whitespace and newlines before comparison.
|
|
||||||
|
|
||||||
**Tests:** [tests/test_sysfs_read.cxx](tests/test_sysfs_read.cxx) — covers all five status branches by writing controlled content to a temporary file.
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
// SysfsRead.hpp
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier GPL-3.0-or-later
|
|
||||||
// Author: Unai Blazquez Gomez <unaibg2000@gmail.com>
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
enum class SysfsStatus
|
|
||||||
{
|
|
||||||
/// @brief File cannot be opened or does not exist.
|
|
||||||
Unreachable,
|
|
||||||
/// @brief File exists but is just empty.
|
|
||||||
Empty,
|
|
||||||
/// @brief File content indicates taht production is enabled (e.g. "1")
|
|
||||||
Enabled,
|
|
||||||
/// @brief File requests a cooldown ("error: temp too high")
|
|
||||||
ErrorTempTooHigh,
|
|
||||||
/// @brief File contains an UnexpectedValue; producer must not send.
|
|
||||||
UnexpectedValue
|
|
||||||
};
|
|
||||||
|
|
||||||
class SysfsReader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// @brief Construct a SysfsReader bound to a specific input file path.
|
|
||||||
/// @param input_path Path to the sysfs-like input file.
|
|
||||||
explicit SysfsReader(const std::filesystem::path& input_path);
|
|
||||||
|
|
||||||
/// @brief Read and interpret the current status of the input file.
|
|
||||||
///
|
|
||||||
/// This function never throws on common I/O errors; instead it reports them
|
|
||||||
/// via the SysfsStatus enum.
|
|
||||||
/// @return Interpreted status of the input file
|
|
||||||
SysfsStatus read_status() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// @brief Helper method for trimming trailing whitespaces and
|
|
||||||
/// newline indicators
|
|
||||||
/// @param String from the m_path file
|
|
||||||
static void trim_in_place(std::string& string);
|
|
||||||
std::filesystem::path m_path; // Path to the input file.
|
|
||||||
};
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
// SysfsRead.cxx
|
|
||||||
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
// Author: Unai Blazquez <unaibg2000@gmail.com>
|
|
||||||
|
|
||||||
#include "SysfsRead.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
SysfsReader::SysfsReader(const std::filesystem::path& input_path)
|
|
||||||
: m_path(input_path)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SysfsStatus SysfsReader::read_status() const
|
|
||||||
{
|
|
||||||
std::ifstream input_file_stream(m_path);
|
|
||||||
if (!input_file_stream.is_open())
|
|
||||||
{
|
|
||||||
return SysfsStatus::Unreachable;
|
|
||||||
}
|
|
||||||
std::stringstream buffer;
|
|
||||||
buffer << input_file_stream.rdbuf(); // read entire stream into buffer
|
|
||||||
std::string contents = buffer.str();
|
|
||||||
|
|
||||||
trim_in_place(contents); // clean input string
|
|
||||||
// compare
|
|
||||||
if (contents.empty())
|
|
||||||
{
|
|
||||||
return SysfsStatus::Empty;
|
|
||||||
}
|
|
||||||
if (contents == "1")
|
|
||||||
{
|
|
||||||
return SysfsStatus::Enabled;
|
|
||||||
}
|
|
||||||
if (contents == "error: temp too high")
|
|
||||||
{
|
|
||||||
return SysfsStatus::ErrorTempTooHigh;
|
|
||||||
}
|
|
||||||
return SysfsStatus::UnexpectedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SysfsReader::trim_in_place(std::string& string)
|
|
||||||
{
|
|
||||||
// left trim
|
|
||||||
string.erase(string.begin(),
|
|
||||||
std::find_if(string.begin(), string.end(), [](unsigned char ch)
|
|
||||||
{ return !std::isspace(ch); }));
|
|
||||||
|
|
||||||
// right trim
|
|
||||||
string.erase(std::find_if(string.rbegin(), string.rend(),
|
|
||||||
[](unsigned char ch) { return !std::isspace(ch); })
|
|
||||||
.base(),
|
|
||||||
string.end());
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
# Author: Unai Blazquez
|
|
||||||
# License: GPL-3-only
|
|
||||||
|
|
||||||
add_executable(test_sysfs_reader
|
|
||||||
test_sysfs_read.cxx
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(test_sysfs_reader
|
|
||||||
PRIVATE
|
|
||||||
core
|
|
||||||
gtest
|
|
||||||
gtest_main
|
|
||||||
)
|
|
||||||
add_test(NAME test_sysfs_reader COMMAND test_sysfs_reader)
|
|
||||||
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "SysfsRead.hpp"
|
|
||||||
|
|
||||||
TEST(SysfsReaderTest, ReturnsEnabledWhenFileContainsOne)
|
|
||||||
{
|
|
||||||
// Arrange create the file and write "1\n" into it.
|
|
||||||
{
|
|
||||||
std::ofstream out("fake_sysfs_input");
|
|
||||||
out << "1\n";
|
|
||||||
// out is closed automatically at the end of this scope
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) Act: construct the reader and read the status.
|
|
||||||
SysfsReader reader{"fake_sysfs_input"};
|
|
||||||
SysfsStatus status = reader.read_status();
|
|
||||||
// 3) Assert: we expect Enabled.
|
|
||||||
EXPECT_EQ(status, SysfsStatus::Enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SysfsReaderTest, ReturnsEmptyWhenFileIsEmpty)
|
|
||||||
{
|
|
||||||
// Arrange: create the file and don't write anything
|
|
||||||
{
|
|
||||||
std::ofstream out("fake_sysfs_input");
|
|
||||||
out << "";
|
|
||||||
}
|
|
||||||
SysfsReader reader{"fake_sysfs_input"};
|
|
||||||
SysfsStatus status1 = reader.read_status();
|
|
||||||
|
|
||||||
{
|
|
||||||
std::ofstream out("fake_sysfs_input");
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
SysfsReader reader_2{"fake_sysfs_input"};
|
|
||||||
SysfsStatus status2 = reader_2.read_status();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
EXPECT_EQ(status1, SysfsStatus::Empty);
|
|
||||||
EXPECT_EQ(status2, SysfsStatus::Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SysfsReaderTest, ReturnsUnexpectedValue)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::ofstream out("fake_sysfs_input");
|
|
||||||
out << "tdd development";
|
|
||||||
}
|
|
||||||
SysfsReader reader{"fake_sysfs_input"};
|
|
||||||
SysfsStatus status = reader.read_status();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
EXPECT_EQ(status, SysfsStatus::UnexpectedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SysfsReaderTest, ReturnsErrorTempTooHigh)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::ofstream out("fake_sysfs_input");
|
|
||||||
out << "error: temp too high";
|
|
||||||
}
|
|
||||||
SysfsReader reader{"fake_sysfs_input"};
|
|
||||||
SysfsStatus status = reader.read_status();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
EXPECT_EQ(status, SysfsStatus::ErrorTempTooHigh);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SysfsReaderTest, ReturnsUnreachableWhenDoesntExist)
|
|
||||||
{
|
|
||||||
SysfsReader reader{"nonexistent_sysfs_input"};
|
|
||||||
SysfsStatus status = reader.read_status();
|
|
||||||
// Assert
|
|
||||||
EXPECT_EQ(status, SysfsStatus::Unreachable);
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user