Testing with assert
and Makefiles
In this section, we will be working on one of the functions that is part of PA2 and provide a cool way to incorporate unit testing into your main()
functions without needing to change/comment lots of lines of code!
Finally, we will introduce a convenient way to compile our programs using Makefiles
and the make
utility!
Testing with assert
Task: While on your ieng6
account within your PA2 repo directory perform the following steps:
-
Open your
pwcrack.c
file that we created/renamed in the previous portion of the lab. We are providing an incomplete implementation of thehex_to_byte
function. Add the following function to your C file and complete it by determining what the function should return. To see the function's intended behavior, refer to the PA2 spec found here.NOTE: If you have already implemented your own
hex_to_byte
function, you can skip this step.#include <stdlib.h> #include <stdio.h> #include <stdint.h> uint8_t hex_to_byte(unsigned char h1, unsigned char h2) { uint8_t x = 0; uint8_t y = 0; // Convert h1 to a decimal value if (h1 >= '0' && h1 <= '9') { x += h1 - '0'; } else if (h1 >= 'a' && h1 <= 'f') { x += h1 - 'a' + 10; } // Convert h2 to a decimal value if (h2 >= '0' && h2 <= '9') { y += h2 - '0'; } else if (h2 >= 'a' && h2 <= 'f') { y += h2 - 'a' + 10; } // TODO: Determine what the function should return }
-
Now we will need to add a
main()
function to this file to give the program an entrypoint. Copy the following main function into yourpwcrack.c
file.NOTE: If you already have a
main()
function from working on the PA, you can keep it as is and focus on the unit testing portion of the code given below.int main(int argc, char **argv) { // UNIT TESTING SECTION int test = 0; // Set this variable to 1 to run unit tests instead of the entire program if (test) { assert(hex_to_byte('a', '2') == 162); // ADD MORE TESTS HERE. MAKE SURE TO ADD TESTS THAT FAIL AS WELL TO SEE WHAT HAPPENS! printf("ALL TESTS PASSED!\n"); return 0; } // MAIN PROGRAM SECTION if (argc < 2) { printf("Error: not enough arguments provided!\n"); printf("Usage: %s <byte 1 in hex> <byte 2 in hex> ...\n", argv[0]); printf("Example: %s a2 b7 99\n", argv[0]); return 1; } int i = 1; for (; i < argc; i++) { printf("Value of hex byte %s is %d\n", argv[i], hex_to_byte(argv[i][0], argv[i][1])); } }
You will note that this
main()
function serves two purposes:- It parses your command-line arguments to your program and runs your password cracker. In this lab, we will be demonstrating the use of command-line arguments to only test the
hex_to_byte
function but you will extend this to work for your complete password cracker implementation. - The
if
statement at the beginning of themain()
function is a way to unit test specific functions as you work on your PA. Setting the value of thetest
variable to1
will run the code within theif
statement that should have severalassert()
statements to test your individual functions (we have provided an example test forhex_to_byte
). If all your tests pass, the program will printALL TESTS PASSED!
and exit successfully. If not, you will receive an error when you run your program withint test = 1;
.
- It parses your command-line arguments to your program and runs your password cracker. In this lab, we will be demonstrating the use of command-line arguments to only test the
- Commit and push your changes to Github. Make sure to include the new files you created in your commit.
In your notes: Briefly explain what you had the hex_to_byte
function return and why?
Makefiles
Thus far, we have been typing out the various gcc
commands needed to compile our C programs. We have also learned some command-line flags that can be useful when compiling our programs like -g
for debugging information, -std=c11
to use the correct C version when compiling on ieng6
and -fsanitize
for memory errors. Wouldn't it be nice if we could just type one command and have all the necessary files compiled with the correct flags? This is where make
comes in.
make
is a utility for building C programs. A Makefile
is a file that contains a set of rules that tell the make
utility what commands it should run for that rule. We will be creating a Makefile
with rules to compile our C programs with the correct flags and dependencies.
Task: Perform the following steps to create a Makefile
for your PA2 project:
-
In your PA2 repository, create a new file named
Makefile
and add the following content to it:all: pwcrack pwcrack: pwcrack.c gcc -std=c11 -Wall -Wno-unused-variable -fsanitize=address -g pwcrack.c -o pwcrack clean: rm -f pwcrack
IMPORTANT NOTE: The indentation in the
Makefile
is done with aTAB
character, not spaces. Make sure to use aTAB
character when indenting the commands in theMakefile
.NOTE: If your file names are different than what is given above at this point, change the rules to match the file names you are using.
-
Now, in your terminal, run
make all
. This will perform the same operation as runninggcc -std=c11 -fsanitize=address -g pwcrack.c -o pwcrack.out
without needing to type or remember that command! You should see thepwcrack
file in your directory. However, if you runmake all
again, you will see that it doesn't recompile the files because they have not changed since the last time they were compiled. This is one of the benefits of usingmake
to compile your programs. -
Now run
make clean
. This should delete the executable file. -
Next, run just
make
with no arguments.
In your notes: What happened when you ran make
without any arguments? Why do you think this is the case?
We now have a clean and simple way to compile our C programs with the correct flags and dependencies using make
. This will be very useful as we continue to work on our PA2 project and need to compile our programs multiple times.
If you are done early
- Work on PA2! Use the remaining time in lab to make progress on PA2 along with your group members and your tutor!
- Try adding a separate rule that would build pwcrack without address sanitizer enabled. Rename the rules so that one generates
pwcrack.asan
, and the other generatespwcrack
. You may need to adjustall
andclean
as well to work correctly with this. - If you are done with PA2 here is a fun extension you could work on: Extend your password cracker such that when given a hash, it will attempt to go through all possible passwords of length 6 until the password is found.