The topics covered on this page includes:
In order to test your code on ecelinux.uwaterloo.ca, you require a machine with an FTP client and a Secure Shell client. You can read how to transfer your files and to use the remote login at the tutorial on using these facilities.
For example, in Project 1, you are required to write and test a Single_list class. First, log onto the machine ecelinux.uwaterloo.ca using the SSh client. You will use your UW User ID together with your Nexus password. In your home directory, you should create a subdirectory appropriate for this course:
$ mkdir ece250 $ mkdir ece250/lab1 $ cd ece250/lab1
Recall that in Linux and other Unix systems, the directory divider is / and not \ as in Microsoft MS DOS and Windows.
Using the FTP client, you can now navigate to this directory and copy your code here. You can list the contents of the directory in the SSh client and you should see a minimum of the following files:
$ ls double.in Exception.h Single_list_driver.cpp Single_node.h double.out int.in Single_list.h Single_node_tester.h ece250.h int.out Single_list_tester.cpp Tester.h
You are now ready to compile and test your code:
$ g++ Single_list_driver.cpp
Recall that you can use command completion on ecelinux. For example, if you start with
$ g++ STab
the shell will complete your command to greatest common part:
$ g++ Single_
Typing l followed by Tab, again, takes us from
$ g++ Single_lTab
to
$ g++ Single_list
Typing _i followed by Tab, again, takes us from
$ g++ Single_list_iTab
to
$ g++ Single_list_driver.cpp
At this point, if you hit Enter, it will compile. If all was successful, you will see another prompt. If there is a compilation error, error messages will be printed out.
We will assume at this point that compilation was success and later we will discuss dealing with compilation errors. If you list the directory contents, you will see a new file, a.out. We will want to execute this file, but Unix will only run executables in specific locations dictated by the PATH environment variable. To run the a.out in this directory, you must say the a.out executable in this directory, as follows:
$ ./a.out int 1 %
You are greeted by a prompt. This is a testing environment, so to begin, we must create a new instance of your single list class:
$ ./a.out int 1 % new Okay
You can continue using commands that you can find at the top of your Single_list_tester.h file. For example,
$ ./a.out int 1 % new Okay 2 % empty 1 Okay 3 % push_front 4 Okay 4 % empty 0 Okay 5 % front 4 Okay
Suppose your implementation is wrong: perhaps you forgot to correctly implement size(). In this case, you will either get a warning or an error:
6 % size 1 Failure in size(): expecting the value '1' but got '0'
The warning is very specific: the function that was being called, the expected value as specified by the command, and the actual value that was received when the member function size() was called on the argument.
We can conclude this testing session by first deleting the object we created, then checking that all memory was correctly cleaned up, and then actually editing.
7 % delete Okay 8 % summary Memory allocated minus memory deallocated: 0 9 % exit Okay Finishing Test Run $
Note, if your destructor or some other member function did not correctly deallocate memory, the number at the end of the summary command will be non-zero. You can use the details command to see the exact memory that was allocated and which was correctly deallocated and which was not.
The tester file for Single_list_int_driver.cpp is the text file int.in. If your code is working correctly, you will see something like:
$ g++ Single_list_driver.cpp $ ./a.out int < int.in Starting Test Run 1 % Okay 2 % Okay 3 % Okay 4 % Okay 5 % Okay 6 % Okay 7 % Okay 8 % Okay 9 % Okay 10 % Okay 11 % Okay 12 % Okay 13 % Okay 14 % Okay 15 % Okay 16 % Okay 17 % Okay 18 % Okay 19 % Okay 20 % Okay 21 % Okay 22 % Okay 23 % Okay 24 % Okay 25 % Okay 26 % Okay 27 % Okay 28 % Okay 29 % Okay 30 % Okay 31 % Memory allocated minus memory deallocated: 0 32 % Okay Finishing Test Run $
The redirect < int.in indicates to the shell that rather than getting input from the user, it should take the contents of the file int.in as the input to the command.
You should compare the output with the content of int.out by using the cat (concatenate) command to print the file to the screen:
$ cat int.out Starting Test Run 1 % Okay 2 % Okay 3 % Okay 4 % Okay 5 % Okay 6 % Okay 7 % Okay 8 % Okay 9 % Okay 10 % Okay 11 % Okay 12 % Okay 13 % Okay 14 % Okay 15 % Okay 16 % Okay 17 % Okay 18 % Okay 19 % Okay 20 % Okay 21 % Okay 22 % Okay 23 % Okay 24 % Okay 25 % Okay 26 % Okay 27 % Okay 28 % Okay 29 % Okay 30 % Okay 31 % Memory allocated minus memory deallocated: 0 32 % Okay Finishing Test Run $
Marking is as follows: if your output matches, you get 1/1, if it does not match, you get 0/1.
If you want to repeat the previous command, use
$ !!
More useful, if you want to repeat the compilation command, you can use either
$ !g
or
$ !g+
if you happened to have used a command starting with g (this author uses gvim as an editor, so he will use !g+ to execute the last compilation command and !gv to execute the last command to edit a file.
Rather than always typing ./a.out int or ./a.out int < int.in, you can use
$ !.
If you want to see a full history of your commands, type
$ history 46 13:15 g++ Single_list_driver.cpp 47 13:15 ./a.out int < int.in 48 13:15 pico Single_list.h 49 13:15 ./a.out int 50 13:15 history $
The command history lists and numbers all the commands you made and you can re-execute one of those commands by using !n. For example, in this case, if you type !., it will execute ./a.out int; however, you may wish to execute the 47th command:
$ !47 ./a.out int < int.in Starting Test Run 1 % Okay 2 % Okay 3 % Okay 4 % Okay ...
Suppose you want to write your own input files instead of having to type commands over and over again. For example, suppose you create a singly linked list containing the entries 5, 3, 7, 7, 4, in that order. If you call erase( 7 ) on that singly linked list, the return value should be two (2) as two nodes containing 7 should have been removed. Following this, the size of the linked list should be 3. You can then write a test file using the text editor:
$ nano test1.in
and you can type the commands as you would expect them to execute:
new push_front 4 push_front 7 push_front 7 push_front 3 push_front 5 size 5 erase 7 2 size 3 delete summary exit
Because this file contains what you would consider to be a valid test for a functioning singly linked list, the output should all be Okay:
$ ./a.out int < test1.in Starting Test Run 1 % Okay 2 % Okay 3 % Okay 4 % Okay 5 % Okay 6 % Okay 7 % Okay 8 % Okay 9 % Okay 10 % Okay 11 % Memory allocated minus memory deallocated: 0 12 % Okay Finishing Test Run $
You are welcome to create such tests and to pass them to your classmates.
If you get something else, you should ask yourself: "Is the test file correctly testing a linked list, or is there a bug in my code?"
If your file does not compile, the compiler tries very hard to give you information as to where it failed. For example, if the signature of the member functions do not match, you might get an error like:
$ g++ Single_list_driver.cpp Single_list.h:154: error: prototype for 'Type Single_list::front(int) const' does not match any in class 'Single_list ' Single_list.h:41: error: candidate is: Type Single_list ::front() const Single_list.h:154: error: template definition of non-template 'Type Single_list ::front(int) const'
It tells you which line the error is on, and it tries to describe the problem. Suppose you forgot a semicolon:
g++ Single_list_driver.cpp Single_list.h: In member function 'int Single_list::count(const Type&) const' Single_list.h:198: error: expected `;' before '}' token
In this case, a line immediately before a closing brace did not have a semicolon.
Suppose you included an end-of-line comment but instead of having two slashes, you only had one. This will be a little different because / is the division operator, so it will attempt to parse the file as if it was a division operator:
g++ Single_list_driver.cpp Single_list.h: In member function 'Type Single_list::pop_front()' Single_list.h:270: error: expected primary-expression before '/' token Single_list.h:270: error: 'Access' not declared in this scope Single_list.h:270: error: expected ';' before 'the'
You will note that there are three errors reported: