#include "tests.h"
#include <iostream>
#include "calculator.h"
int main()
{
// Calculator c;
// std::cout << c.Calculate('%', 6, 7);
RunTests();
return 0;
}
#ifndef CALCULATOR_H_
#define CALCULATOR_H_
#include <functional>
#include <map>
#include <unordered_map>
class Calculator {
public:
using operation_key = char;
using value_type = double;
private:
using BinaryOperation = std::function<value_type(value_type, value_type)>;
// Assuming only C-Style function pointers should be supported
// using BinaryOperation = value_type (*)(value_type, value_type); // C++11 only
// typedef value_type (*BinaryOperation)(value_type, value_type); // old syntax
using ValidOperations = std::map<operation_key, BinaryOperation>;
static const ValidOperations operations_;
operation_key last_operation_ = '+';
public:
value_type Calculate(operation_key operation, value_type left_operand,
value_type right_operand) noexcept;
operation_key GetLastOperation() const noexcept;
};
#endif // CALCULATOR_H_
#include "calculator.h"
#include <cmath>
double plus_function(double lhs, double rhs) { return lhs + rhs; }
struct minus_functor {
double operator()(double lhs, double rhs) { return lhs - rhs; }
};
const Calculator::ValidOperations Calculator::operations_ = {
// {'+', [](auto lhs, auto rhs) { return lhs + rhs; }},
{'+', plus_function },
// {'-', [](auto lhs, auto rhs) { return lhs - rhs; }},
{'-', minus_functor{} },
{'*', [](auto lhs, auto rhs) { return lhs * rhs; }},
{'/', [](auto lhs, auto rhs) { return lhs / rhs; }},
};
char Calculator::GetLastOperation() const noexcept { return last_operation_; }
double Calculator::Calculate(const char operation, const double left_operand,
const double right_operand) noexcept
{
// const auto result = operations_.find(operation);
// if (result == operations_.end()) {
// return std::nan("NaN");
// }
last_operation_ = operation;
try {
return operations_.at(operation)(left_operand, right_operand);
}
catch (std::out_of_range &) {
return std::nan("NaN");
}
}
#ifndef TESTS_H_
#define TESTS_H_
void RunTests();
#endif // TESTS_H_
#include "tests.h"
#include "test_functions.h"
#include "calculator.h"
TEST(TestCalculatorAddition)
{
Calculator calc;
const auto first_value = 2.1;
const auto second_value = 4.2;
ASSERT(calc.Calculate('+', first_value, second_value) ==
first_value + second_value,
"Addition failed");
}
TEST(TestCalculatorSubtraction)
{
Calculator calc;
const auto first_value = 2.1;
const auto second_value = 4.2;
ASSERT(calc.Calculate('-', first_value, second_value) ==
first_value - second_value,
"Subtraction failed");
}
TEST(TestCalculatorMultiply)
{
Calculator calc;
const auto first_value = 2.1;
const auto second_value = 4.2;
ASSERT(calc.Calculate('*', first_value, second_value) ==
first_value * second_value,
"Multiply failed");
}
TEST(TestCalculatorDivision)
{
Calculator calc;
const auto first_value = 2.1;
const auto second_value = 4.2;
ASSERT(calc.Calculate('/', first_value, second_value) ==
first_value / second_value,
"Division failed");
}
TEST(TestCalculatorLastOperation)
{
const auto operation = '/';
Calculator calc;
const auto first_value = 2.1;
const auto second_value = 4.2;
calc.Calculate(operation, first_value, second_value);
ASSERT(calc.GetLastOperation() == operation, "GetLastOperation failed");
}
TEST_SUITE(TestAddressManagement)
{
RUN_TEST(TestCalculatorAddition);
RUN_TEST(TestCalculatorSubtraction);
RUN_TEST(TestCalculatorMultiply);
RUN_TEST(TestCalculatorDivision);
RUN_TEST(TestCalculatorLastOperation);
}
void RunTests() { RUN_TEST_SUITE(TestAddressManagement); }
// Copyright 2018 MicroConsult GmbH
#ifndef TEST_FUNCTIONS_H_
#define TEST_FUNCTIONS_H_
#include <stdio.h>
static const int test_message_buffer_size = 1024;
static char test_message_buffer[test_message_buffer_size];
#define TEST(fx) static void fx(const char** message)
#define TEST_SUITE(fx) void fx(int* tests_total, int* tests_successful)
#define RUN_TEST(test) \
do { \
const char* message = nullptr; \
++*tests_total; \
test(&message); \
if (message) { \
printf("--- ERROR (%s): %s \n", #test, message); \
} \
else { \
++*tests_successful; \
printf("+++ passed: %s\n", #test); \
} \
} while (0)
#define RUN_TEST_SUITE(test_suite) \
do { \
int tests_total = 0; \
int tests_successful = 0; \
test_suite(&tests_total, &tests_successful); \
printf("-----------------------------------------------\n"); \
if (tests_successful == tests_total) { \
printf("+ Test Suite '%s': all %d tests passed\n\n", #test_suite, \
tests_total); \
} \
else { \
printf("- Test Suite '%s': %d of %d tests passed\n\n", #test_suite, \
tests_successful, tests_total); \
} \
} while (false)
#define ASSERT(test, error_message) \
do { \
if (test) { \
*message = nullptr; \
} \
else { \
snprintf(test_message_buffer, test_message_buffer_size - 1, \
error_message); \
*message = test_message_buffer; \
return; \
} \
} while (false)
#define ASSERT_INT(value, expected) \
do { \
if (value == expected) { \
*message = nullptr; \
} \
else { \
snprintf(test_message_buffer, test_message_buffer_size - 1, \
"Wrong value - expected: %d, current value: %d", expected, \
value); \
*message = test_message_buffer; \
return; \
} \
} while (false)
#endif // TEST_FUNCTIONS_H_