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++
|
||||
# build artifacts
|
||||
build/
|
||||
# Prerequisites
|
||||
*.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 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.
|
||||
Azkoyen technical test implementation. Implemented (mostly) on standard c++ 17 framework, but with Qt wherever was necessary
|
||||
@ -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