Skip to content
Snippets Groups Projects
Commit 290379b2 authored by Jacek Galowicz's avatar Jacek Galowicz
Browse files

First commit

parents
No related branches found
No related tags found
No related merge requests found
Makefile 0 → 100644
override CXXFLAGS += -std=c++17 -Isrc
default: calc
calc: src/main.cpp src/calc.cpp
$(CXX) $(CXXFLAGS) -o $@ $^
unit_test: test/main.o test/test.o src/calc.o
$(CXX) $(CXXFLAGS) -o $@ $^ -Isrc
run_test: unit_test
./unit_test
fuzz_calc: src/main.cpp src/calc.cpp
afl-g++ $(CXXFLAGS) -o $@ $^
fuzz: fuzz_calc
rm -rf out
afl-fuzz -i in -o out -- ./fuzz_calc
clean:
rm -rf calc fuzz_calc unit_test out src/*.o test/*.o
with import (import ./nixpkgs.nix) {};
stdenv.mkDerivation {
name = "rpn-calculator";
src = ./.;
buildInputs = [ catch2 ];
doCheck = true;
checkTarget = "run_test";
installPhase = ''
mkdir -p $out
find . -executable -type f -exec cp {} $out \;
'';
}
#!/usr/bin/env bash
fuzz_seconds=${1:-10} # 10 seconds by default
echo "Going to fuzz for $fuzz_seconds seconds."
set -e
afl-fuzz -i in -o out -- ./fuzz_calc &
afl_pid=$!
sleep $fuzz_seconds
kill $afl_pid
11+3+2/
11/
builtins.fetchTarball {
url = "https://github.com/nixos/nixpkgs/archive/859ce47b023d80ccbcf446a112c813972a5949b6.tar.gz";
sha256 = "14rmrpzbxbf8p4v70n39bvxm9qhnwlg4pjkzf7ya6n697g8yd1wx";
}
with import (import ./nixpkgs.nix) {};
let
rpncalc = import ./default.nix;
afl_rpncalc = rpncalc.overrideAttrs (_: {
nativeBuildInputs = [ afl ];
makeFlags = [ "fuzz_calc" ];
doCheck = false;
});
in {
inherit rpncalc afl_rpncalc;
sanitized = rpncalc.overrideAttrs (_: {
CXXFLAGS = "-fsanitize=undefined -fsanitize=address";
});
fuzz_rpncalc = afl_rpncalc.overrideAttrs (o: {
nativeBuildInputs = o.nativeBuildInputs ++ [ gnuplot which ];
preConfigure = ''
patchShebangs fuzz_seconds.sh
'';
postBuild = ''
./fuzz_seconds.sh 10
afl-plot out graph
'';
installPhase = ''
cp -r out $out
cp -r graph $out/
mkdir -p $out/nix-support
echo report testlog $out graph/index.html > $out/nix-support/hydra-build-products
'';
});
}
#include "calc.hpp"
#include <stack>
#include <stdexcept>
int plus( int a, int b) { return a + b; }
int minus( int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide( int a, int b) { return a / b; }
int pop_stack(auto &stack) {
const auto ret{stack.top()};
stack.pop();
return ret;
}
void change_stack_state(auto &operation, auto &stack) {
const auto op_b{pop_stack(stack)};
const auto op_a{pop_stack(stack)};
stack.push(operation(op_a, op_b));
}
int evaluate(const std::string &s) {
std::stack<int> stack;
for (const char c : s) {
switch (c) {
case '+': change_stack_state(plus, stack); break;
case '-': change_stack_state(minus, stack); break;
case '*': change_stack_state(multiply, stack); break;
case '/': change_stack_state(divide, stack); break;
case '0'...'9': stack.push(c - '0'); break;
}
}
return {stack.top()};
}
#pragma once
#include <string>
int evaluate(const std::string &s);
#include "calc.hpp"
#include <iostream>
int main() {
std::string user_input;
std::cin >> user_input;
if (user_input.empty()) { std::cout << "Empty input\n"; return 1; }
std::cout << "User input is \"" << user_input << "\"\n";
const int result{evaluate(user_input)};
std::cout << "Result is: " << result << '\n';
}
#include <calc.hpp>
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <calc.hpp>
#include <catch2/catch.hpp>
TEST_CASE( "some example calculations", "[calc]") {
REQUIRE( evaluate("11+") == 2 );
REQUIRE( evaluate("12+2-3*") == 3 );
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment