diff --git a/src/checker.c b/src/checker.c index 6d47d16..fbc4cf8 100644 --- a/src/checker.c +++ b/src/checker.c @@ -15,7 +15,7 @@ #include #include -void execute_move(const char *move, t_state *state) +int execute_move(const char *move, t_state *state) { const t_move moves[11] = {&sa, &sb, &ss, &pa, &pb, \ &ra, &rb, &rr, &rra, &rrb, &rrr}; @@ -31,21 +31,39 @@ void execute_move(const char *move, t_state *state) if (ft_strcmp(move, moves_names[i]) == 0) { moves[i](state, 1); - return ; + return (1) ; } i++; } - ft_putstr_fd("Error: Invalid move\n", 2); + return (0); +} +int read_moves(t_state *state) +{ + char *move; + int ret; + + move = get_next_line(STDIN_FILENO); + while (move) + { + ret = execute_move(move, state); + free(move); + if (!ret) + return (0); + move = get_next_line(STDIN_FILENO); + } + free(move); + return (1); } int main(int argc, char *argv[]) { int size; t_state *state; - char *move; - if (!initialise_state(&state) || argc == 1) + if (!initialise_state(&state)) return (ft_putstr_fd("Error\n", STDERR_FILENO), 1); + if (argc == 1) + return (free_state(state), 1); while (argc-- > 1) { if (!new_element(&(state->a), argv[argc])) @@ -54,14 +72,8 @@ int main(int argc, char *argv[]) if (has_duplicates(state->a)) return (error(state)); size = ft_lstsize(state->a); - move = get_next_line(STDIN_FILENO); - while (move) - { - execute_move(move, state); - free(move); - move = get_next_line(STDIN_FILENO); - } - free(move); + if (!read_moves(state)) + return (error(state)); if (ft_lstsize(state->a) == size && (size == 0 || is_sorted(state->a))) return (free_state(state), ft_printf("OK\n")); return (free_state(state), ft_printf("KO\n")); diff --git a/src/push_swap.c b/src/push_swap.c index 4d2ef78..a3a333e 100644 --- a/src/push_swap.c +++ b/src/push_swap.c @@ -20,8 +20,10 @@ int main(int argc, char *argv[]) t_state *state; state = NULL; - if (!initialise_state(&state) || argc == 1) + if (!initialise_state(&state)) return (ft_putstr_fd("Error\n", STDERR_FILENO), 1); + if (argc == 1) + return (1); while (argc-- > 1) { if (!new_element(&(state->a), argv[argc])) diff --git a/tester.sh b/tester.sh index a63fc47..4d3bb60 100755 --- a/tester.sh +++ b/tester.sh @@ -12,6 +12,7 @@ run_test_case() { MAX=0 MIN=10000000 AVG=0 + SUM_SQUARES=0 ITER=$2 N=$1 MAX_ARGS="" @@ -24,8 +25,9 @@ run_test_case() { run_iteration() { local iter=$1 local ARG=$(seq -1000 1000 | shuf -n $N) - local OPS=$(./push_swap $ARG | wc -l | tr -d '[:space:]') - local OK=$(./push_swap $ARG | ./checker $ARG | tr -d '[:space:]') + local OPS_OK=$(./push_swap $ARG | tee >(wc -l | tr -d '[:space:]' > "$TMP_DIR/ops_$iter") | ./checker $ARG | tr -d '[:space:]') + local OPS=$(cat "$TMP_DIR/ops_$iter") + local OK=$OPS_OK echo "$OPS" > "$TMP_DIR/ops_$iter" echo "$ARG" > "$TMP_DIR/arg_$iter" @@ -46,6 +48,7 @@ run_test_case() { local ARG=$(cat "$TMP_DIR/arg_$iter") local OK=$(cat "$TMP_DIR/ok_$iter") AVG=$((AVG + OPS)) + SUM_SQUARES=$((SUM_SQUARES + OPS * OPS)) if [ "$OPS" -gt "$MAX" ]; then MAX=$OPS @@ -72,7 +75,9 @@ run_test_case() { done AVG=$((AVG / ITER)) - echo -e "Testing $BOLD$N elements $ITER times:$NC max:$GREEN $MAX$NC min:$RED $MIN$NC avg:$AVG" + VARIANCE=$((SUM_SQUARES / ITER - AVG * AVG)) + STDDEV=$(echo "sqrt($VARIANCE)" | bc -l) + echo -e "Testing\t $BOLD$N \telements $ITER times:$NC \t\tmax:$GREEN $MAX$NC\t\tmin:$RED $MIN$NC\t\tavg: $AVG\t\tstddev: $(printf "%.2f" $STDDEV)" # echo "Iterations: $ITER" # echo "Max: $MAX" # echo "Min: $MIN" @@ -90,177 +95,186 @@ run_test_case() { rm -rf "$TMP_DIR" } - +check_output() { + local output=$1 + local expected=$2 + local message=$3 + if [ "$output" == "$expected" ]; then + echo -e "${message}: ${GREEN}OK${NC}" + else + echo -e "${message}: ${RED}KO${NC}" + fi +} # Test push_swap with non-numeric arguments -NON_NUMERIC_ARGS="a b c" -NON_NUMERIC_OUTPUT=$(./push_swap $NON_NUMERIC_ARGS 2>&1 >/dev/null) -if [ "$NON_NUMERIC_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Non-numeric argument test passed${NC}" -else - echo -e "${RED}Non-numeric argument test failed${NC}" -fi - -# Test checker with non-numeric arguments -NON_NUMERIC_OUTPUT=$(./checker $NON_NUMERIC_ARGS 2>&1 >/dev/null) -if [ "$NON_NUMERIC_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Non-numeric argument test passed${NC}" -else - echo -e "${RED}Non-numeric argument test failed${NC}" -fi +ARGS="a b c" +OUTPUT=$(./push_swap $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "1. Test push_swap with non-numeric arguments" # Test push_swap with duplicate arguments -DUPLICATE_ARGS="1 1 2 3" -DUPLICATE_OUTPUT=$(./push_swap $DUPLICATE_ARGS 2>&1 >/dev/null) -if [ "$DUPLICATE_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Duplicate argument test passed${NC}" -else - echo -e "${RED}Duplicate argument test failed${NC}" -fi - -# Test checker with duplicate arguments -DUPLICATE_OUTPUT=$(./checker $DUPLICATE_ARGS 2>&1 >/dev/null) -if [ "$DUPLICATE_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Duplicate argument test passed${NC}" -else - echo -e "${RED}Duplicate argument test failed${NC}" -fi +ARGS="1 1 2 3" +OUTPUT=$(./push_swap $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "2. Test push_swap with duplicate arguments" # Test push_swap with empty arguments -EMPTY_OUTPUT=$(./push_swap 2>&1 >/dev/null) -if [ "$EMPTY_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Empty argument test passed${NC}" -else - echo -e "${RED}Empty argument test failed${NC}" -fi - -# Test checker with empty arguments -EMPTY_OUTPUT=$(./checker 2>&1 >/dev/null) -if [ "$EMPTY_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Empty argument test passed${NC}" -else - echo -e "${RED}Empty argument test failed${NC}" -fi +OUTPUT=$(./push_swap 2>&1 >/dev/null) +check_output "$OUTPUT" "" "3. Test push_swap with empty arguments" # Test push_swap with invalid arguments -INVALID_ARGS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 a" -INVALID_OUTPUT=$(./push_swap $INVALID_ARGS 2>&1 >/dev/null) -if [ "$INVALID_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Invalid argument test passed${NC}" -else - echo -e "${RED}Invalid argument test failed${NC}" -fi - -# Test checker with invalid arguments -INVALID_OUTPUT=$(./checker $INVALID_ARGS 2>&1 >/dev/null) -if [ "$INVALID_OUTPUT" == "Error" ]; then - echo -e "${GREEN}Invalid argument test passed${NC}" -else - echo -e "${RED}Invalid argument test failed${NC}" -fi +ARGS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 a" +OUTPUT=$(./push_swap $ARGS 2>&1) +check_output "$OUTPUT" "Error" "4. Test push_swap with invalid arguments" # Test push_swap with valid arguments -VALID_ARGS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" -VALID_OUTPUT=$(./push_swap $VALID_ARGS 2>&1 >/dev/null) -if [ "$VALID_OUTPUT" != "Error" ]; then - echo -e "${GREEN}Valid argument test passed${NC}" -else - echo -e "${RED}Valid argument test failed${NC}" -fi +ARGS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" +OUTPUT=$(./push_swap $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "" "5. Test push_swap with valid arguments" + +# Run push_swap with only numeric parameters including one greater than MAXINT. The program must display "Error". +OUTPUT=$(./push_swap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 999999999999999 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "6. Test push_swap with only numeric parameters including one greater than MAXINT" + +# Run the following command "$>./push_swap 42". The program should display nothing (0 instruction). +OUTPUT=$(./push_swap 42 2>&1 >/dev/null) +check_output "$OUTPUT" "" "7. Test push_swap with a single argument" + +# Run the following command "$>./push_swap 2 3". The program should display nothing (0 instruction). +OUTPUT=$(./push_swap 2 3 2>&1 >/dev/null) +check_output "$OUTPUT" "" "8. Test push_swap with two ordered arguments" + +# Run the following command "$>./push_swap 0 1 2 3". The program should display nothing (0 instruction). +OUTPUT=$(./push_swap 0 1 2 3 2>&1 >/dev/null) +check_output "$OUTPUT" "" "9. Test push_swap with four ordered arguments" + +# Run the following command "$>./push_swap 'Between 0 and 9 randomly sorted values chosen>'. The program should display nothing (0 instruction). +OUTPUT=$(./push_swap 11 22 33 44 55 66 77 88 99 2>&1 >/dev/null) +check_output "$OUTPUT" "" "10. Test push_swap with nine ordered arguments" + +# Run the following command "$>./push_swap 0 1 2 3 4 5 6 7 8 9". The program should display nothing (0 instruction). +OUTPUT=$(./push_swap 0 1 2 3 4 5 6 7 8 9 2>&1 >/dev/null) +check_output "$OUTPUT" "" "11. Test push_swap with ten ordered arguments" + +# Test checker with non-numeric arguments +ARGS="a b c" +OUTPUT=$(./checker $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "12. Test checker with non-numeric arguments" + +# Test checker with duplicate arguments +ARGS="1 1 2 3" +OUTPUT=$(./checker $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "13. Test checker with duplicate arguments" + +# Test checker with empty arguments +OUTPUT=$(./checker 2>&1 >/dev/null) +check_output "$OUTPUT" "" "14. Test checker with empty arguments" + +# Test checker with invalid arguments +ARGS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 a" +OUTPUT=$(./checker $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "15. Test checker with invalid arguments" # Test checker with valid arguments -VALID_OUTPUT=$(./push_swap $VALID_ARGS | ./checker $VALID_ARGS) -if [ "$VALID_OUTPUT" == "OK" ]; then - echo -e "${GREEN}Valid argument test passed${NC}" -else - echo -e "${RED}Valid argument test failed${NC}" -fi +ARGS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" +OUTPUT=$(./push_swap $ARGS | ./checker $ARGS) +check_output "$OUTPUT" "OK" "16. Test push_swap and checker with ordered list" -#Run push_swap with non numeric parameters. The program must display "Error". -OUTPUT=$(./push_swap a b c) -if [ "$OUTPUT" == "Error" ]; then - echo -e "${GREEN}Non-numeric argument test passed${NC}" -else - echo -e "${RED}Non-numeric argument test failed${NC}" -fi - -#Run push_swap with a duplicate numeric parameter. The program must display "Error". -OUTPUT=$(./push_swap 1 1 2 3) -if [ "$OUTPUT" == "Error" ]; then - echo -e "${GREEN}Duplicate argument test passed${NC}" -else - echo -e "${RED}Duplicate argument test failed${NC}" -fi - -#Run push_swap with only numeric parameters including one greater than MAXINT. The program must display "Error". -OUTPUT=$(./push_swap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 999999999999999) -if [ "$OUTPUT" == "Error" ]; then - echo -e "${GREEN}Invalid argument test passed${NC}" -else - echo -e "${RED}Invalid argument test failed${NC}" -fi - -#Run push_swap without any parameters. The program must not display anything and give the prompt back. -OUTPUT=$(./push_swap) -if [ "$OUTPUT" == "" ]; then - echo -e "${GREEN}Empty argument test passed${NC}" -else - echo -e "${RED}Empty argument test failed${NC}" -fi - -#Run the following command "$>./push_swap 42". The program should display nothing (0 instruction). -OUTPUT=$(./push_swap 42) -if [ "$OUTPUT" == "" ]; then - echo -e "${GREEN}Single argument test passed${NC}" -else - echo -e "${RED}Single argument test failed${NC}" -fi - -#Run the following command "$>./push_swap 2 3". The program should display nothing (0 instruction). -OUTPUT=$(./push_swap 2 3) -if [ "$OUTPUT" == "" ]; then - echo -e "${GREEN}Two arguments test passed${NC}" -else - echo -e "${RED}Two arguments test failed${NC}" -fi - -#Run the following command "$>./push_swap 0 1 2 3". The program should display nothing (0 instruction). -OUTPUT=$(./push_swap 0 1 2 3) -if [ "$OUTPUT" == "" ]; then - echo -e "${GREEN}Four arguments test passed${NC}" -else - echo -e "${RED}Four arguments test failed${NC}" -fi - -#Run the following command "$>./push_swap 0 1 2 3 4 5 6 7 8 9". The program should display nothing (0 instruction). -OUTPUT=$(./push_swap 0 1 2 3 4 5 6 7 8 9) -if [ "$OUTPUT" == "" ]; then - echo -e "${GREEN}Ten arguments test passed${NC}" -else - echo -e "${RED}Ten arguments test failed${NC}" -fi - -#Run the following command "$>./push_swap 'Between 0 and 9 randomly sorted values chosen>'. The program should display nothing (0 instruction). -OUTPUT=$(./push_swap 11 22 33 44 55 66 77 88 99) -if [ "$OUTPUT" == "" ]; then - echo -e "${GREEN}Ten arguments test passed${NC}" -else - echo -e "${RED}Ten arguments test failed${NC}" -fi - -#Run "$>ARG="2 1 0"; ./push_swap $ARG | ./checker_OS $ARG". Check that the checker program displays "OK" and that the size of the list of instructions from push_swap is 2 OR 3. Otherwise the test fails. +# Run "$>ARG="2 1 0"; ./push_swap $ARG | ./checker_OS $ARG". Check that the checker program displays "OK" and that the size of the list of instructions from push_swap is 2 OR 3. Otherwise the test fails. OUTPUT=$(ARG="2 1 0"; ./push_swap $ARG | ./checker $ARG) -if [ "$OUTPUT" == "OK" ]; then - echo -e "${GREEN}Three arguments test passed${NC}" +check_output "$OUTPUT" "OK" "17. Run \"$>ARG=\"2 1 0\"; ./push_swap \$ARG | ./checker_OS \$ARG\". Check that the checker program displays \"OK\"" + +OUTPUT=$(ARG="2 1 0"; ./push_swap $ARG | wc -l) +if [ "$OUTPUT" -lt 3 ]; then + echo -e "18. The size of the list of instructions from push_swap is less than 3: ${GREEN}OK${NC}" else - echo -e "${RED}Three arguments test failed${NC}" + echo -e "18. The size of the list of instructions from push_swap is less than 3: ${RED}KO${NC}" fi -#Run "$>ARG="1 5 2 4 3"; ./push_swap $ARG | ./checker_OS $ARG". Check that the checker program displays "OK" and that the size of the list of instructions from push_swap is 12. Otherwise the test fails. + +# Run "$>ARG="1 5 2 4 3"; ./push_swap $ARG | ./checker_OS $ARG". Check that the checker program displays "OK" and that the size of the list of instructions from push_swap is 12. Otherwise the test fails. OUTPUT=$(ARG="1 5 2 4 3"; ./push_swap $ARG | ./checker $ARG) -if [ "$OUTPUT" == "OK" ]; then - echo -e "${GREEN}Five arguments test passed${NC}" +check_output "$OUTPUT" "OK" "19. Run \"$>ARG=\"1 5 2 4 3\"; ./push_swap \$ARG | ./checker_OS \$ARG\". Check that the checker program displays \"OK\"" + +OUTPUT=$(ARG="1 5 2 4 3"; ./push_swap $ARG | wc -l) + +if [ "$OUTPUT" -lt 12 ]; then + echo -e "20. The size of the list of instructions from push_swap is less than 12: ${GREEN}OK${NC}" else - echo -e "${RED}Five arguments test failed${NC}" + echo -e "20. The size of the list of instructions from push_swap is less than 12: ${RED}KO${NC}" fi +# Run checker with valid parameters and an invalid action +ARGS="1 2 3" +ACTIONS="invalid_action" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "21. Run checker with valid parameters and an invalid action" + +# Run checker with valid parameters and an action with spaces +ARGS="1 2 3" +ACTIONS=" sa \npb\nrrr " +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS 2>&1 >/dev/null) +check_output "$OUTPUT" "Error" "22. Run checker with valid parameters and an action with spaces" + +# Run checker with a specific command and action list +ARGS="0 9 1 8 2 7 3 6 4 5" +ACTIONS="sa\npb\nrrr\n" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "KO" "23. Run checker with specific command and action list" + +# Run checker with a valid list and a valid instruction list that doesn't order the integers +ARGS="4 3 2 1" +ACTIONS="sa\npb\nra\nrra\npa" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "KO" "24. Run checker with valid list and invalid instruction list" + +ARGS="5 1 3 2 4" +ACTIONS="pb\npb\nsa\npa\npa" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "KO" "25. Run checker with valid list and invalid instruction list" + +ARGS="6 5 4 3 2 1" +ACTIONS="pb\npb\npb\nsa\npa\npa\npa" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "KO" "26. Run checker with valid list and invalid instruction list" + +# Run checker with no instructions +ARGS="0 1 2" +OUTPUT=$(echo -e "" | ./checker $ARGS) +check_output "$OUTPUT" "OK" "27. Run checker with no instructions" + +# Run checker with a specific command and valid action list +ARGS="0 9 1 8 2" +ACTIONS="pb\nra\npb\nra\nsa\nra\npa\npa" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "OK" "28. Run checker with specific command and valid action list" + +# Run checker with a valid list and a valid instruction list that orders the integers +ARGS="3 2 1" +ACTIONS="sa\nra\nsa\nrra" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "OK" "29. Run checker with valid list and valid instruction list" + +ARGS="4 1 3 2" +ACTIONS="pb\npb\nsa\npa\npa" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "OK" "30. Run checker with valid list and valid instruction list" + +ARGS="5 4 3 2 1" +ACTIONS="pb\npb\npb\nsa\npa\npa\npa" +OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) +check_output "$OUTPUT" "OK" "31. Run checker with valid list and valid instruction list" + +# Repeat the test with several permutations +for i in {1..5}; do + ARGS=$(seq 1 5 | shuf | tr '\n' ' ') + ACTIONS=$(./push_swap $ARGS) + OUTPUT=$(echo -e "$ACTIONS" | ./checker $ARGS) + check_output "$OUTPUT" "OK" "32. Run checker with random permutation $i" +done + +run_test_case 3 100 +run_test_case 5 100 +run_test_case 7 100 +run_test_case 10 100 +run_test_case 50 1 +run_test_case 100 1 +run_test_case 500 1