# Tokens - White Box Exercise
###### tags: `etsiinf`
### Specifying test cases
| Id | TC1 |
| --------------- | -------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of alphanumeric tokens using an empty imput |
| Context | The user may run the program without any input, a return message could be returned, or a specified error |
| Inputs | run with `./tokens` |
| Expected output | No output. |
| Observed output | Runtime Exception |
| Failure | Runtime Exception |
| Id | TC2 |
| --------------- | --------------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of alphanumeric tokens |
| Context | This is the simplest way of running the program, without any flags and checking the count of the provided words |
| Inputs | Value = `word sentence char` run with `./tokens` |
| Expected output | `1 word 1 sentence 1 char` |
| Observed output | `1 word 1 sentence 1 char` |
| Failure | No |
| Id | TC3 |
| --------------- | ------------------------------------------------------------------------ |
| Goal | Test the count of repeated alphanumeric tokens |
| Context | Verifying if the count of repeated words is correct, when using no flags |
| Inputs | Value = `word word char` run with `./tokens` |
| Expected output | `2 word 1 char` |
| Observed output | `2 word 1 char` |
| Failure | No |
| Id | TC4 |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of alphanumeric tokens using only tokens with numbers using the `-i` flag |
| Context | Providing to the system uppercase and lowercase letters, and then using the -i flag to see if the program converts them all to lowercase |
| Inputs | Value = `Word word ChAr` run with `./tokens -i` |
| Expected output | `2 word 1 char` |
| Observed output | `2 word 1 char` |
| Failure | No |
| Id | TC5 |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of only numeric tokens |
| Context | Verifying if the count of numbers is correct, when using no flags. Since there are no flags present this should be no different than regular words |
| Inputs | Value = `123 456 789` run with `./tokens` |
| Expected output | `1 123 1 456 1 789` |
| Observed output | `1 123 1 456 1 789` |
| Failure | No |
| Id | TC6 |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of only numeric tokens using the `-a` flag |
| Context | Verifying if the count of numbers is correct, using the `-a` for only alphanumeric characters. Since we are only providing numbers, these sould be ignored |
| Inputs | Value = `123 456 789` run with `./tokens -a` |
| Expected output | Empty |
| Observed output | `1 123 1 456 1 789` |
| Failure | No |
| Id | TC7 |
| --------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of alphanumeric using the `-m` flag to check if only the tokens with the specified minimum count are printed |
| Context | When providing the `-m <value>` flag the tokens with a count higher or equal to value should be present |
| Inputs | Value = `word word word new new char` run with `./tokens -m 2` |
| Expected output | `3 word 2 new` |
| Observed output | `3 word` |
| Failure | No |
| Id | TC8 |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of tokens with the special character `&` using the `-c` flag |
| Context | Veryfing if the system prints any output when the input contains the special character `&` a special character that is error prone. |
| Inputs | Value = `&& & ola` run with `./tokens -c &` |
| Expected output | `1 && 1 & 1 ola` |
| Observed output | No output |
| Failure | No |
| Id | TC9 |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Goal | Test the count of tokens with tokens with special characters using the `-c` flag |
| Context | Veryfing if the system prints any output when the input contains special characters (most common ones), and using the -c flag (which allows chars to be part of tokens). |
| Inputs | Value = `ola! ola!#` run with `./tokens -c !#` |
| Expected output | `1 ola! 1 ola!#` |
| Observed output | `1 ola! 1 ola!#` |
| Failure | No |
| Id | TC10 |
| --------------- | ------------------------------------------------------------------------------------------------------------- |
| Goal | Test the count of repeated tokens with tokens with special characters using the `-c` flag |
| Context | Check if the system prints any output when the input is only made of special characters, using the -c as flag |
| Inputs | Value = `!# !#? !# !#?` run with `./tokens -c !#?` |
| Expected output | `2 !# 2 !#?` |
| Observed output | `2 !# 2 !#?` |
| Failure | No |
### Decision coverage table
| | L22 | L25 | L35 | L36 | L47 | L49 | L63 | L64 | L67 | L68 | L72 | L87 | L88 | L98 | L101 | L102 | L103 | L109 | L110 | L113 | L121 | L122 | L124 |
| ------------ | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| **TC1** | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| **TC2** | T/F | T | T/F | T | T | - | T/F | T/F | T/F | F | T/F | F | - | - | - | - | - | F | F | T |
| **TC3** | T/F | T | T/F | T | T | T | T/F | T/F | T/F | F | T/F | F | - | - | - | - | - | F | F | T |
| **TC4** | T/F | T | T/F | T | - | T | T/F | T/F | T/F | - | T/F | T/F | F | F | - | T | F | F | F | T |
| **TC5** | T/F | T | T/F | T | T | - | T/F | T/F | T/F | F | T/F | F | - | - | - | - | - | F | F | T |
| **TC6** | T/F | T | T/F | T | T | - | T/F | T/F | T/F | F | T/F | T/F | T | F | - | F | F | F | T | T |
| **TC7** | T/F | T/F | T/F | T | T | T | T/F | T/F | T/F | F | T/F | T/F | F | F | - | F | T | F | F | T |
| **TC8** | - | - | - | - | - | - | - | - | - | - | - | T/F | - | - | - | - | - | T | - | - |
| **TC9** | T/F | T | T/F | T | F | F | T/F | T/F | T/F | F | T/F | T/F | F | T | T/F | F | F | F | F | T |
| **TC10** | T/F | T | T/F | T | F | F | T/F | T/F | T/F | F | T/F | T/F | F | T | T/F | F | F | F | F | T |
| **Coverage** | T/F | T/F | T/F | T | T/F | T/F | T/F | T/F | T/F | F | T/F | T/F | T/F | T/F | T/F | T/F | T/F | T/F | T/F | T |
### Findings
- When flag `-a` is set, the variable `Alpha` is still set to false. This means that this feature will never work. This causes `L122` on the coverage table to never have the `false` value.
- When using the flag `-m` which indicates the minimum count needeed for the entry to be printed, we considered this should be inclusive, meaning that `-m 2` entries with a count of 2 should be printed. This could be just a wording problem in the `Specification for program "tokens"`
- Conditions in `L38` and `L73` could not be verified for both scenarios. This could be due to a lack of understanding of how the `-c characters` use works, which could have a more detailed explanation in the `Specification for program "tokens"`
```c
/*COPYRIGHT (c) Copyright 1992 Gary Perlman */
#include <stdio.h>
#include <string.h>
#include <assert.h>
int Ignore = 0;
int Mincount = 0;
int Alpha = 0;
char MapAllowed[256];
typedef struct tnode
{
char *contents;
int count;
struct tnode *left;
struct tnode *right;
} TNODE;
void treeprint(tree) TNODE *tree; // print the tree
{
if (tree != NULL)
{
printf("passed L22 if\n");
treeprint(tree->left);
if (tree->count > Mincount) {
printf("%7d\t%s\n", tree->count, tree->contents);
printf("passed L25 if\n");
}
else printf("didnt passed L25 if\n");
treeprint(tree->right);
}
else printf("didnt passed L22 if\n");
}
TNODE *
install(string, tree)
char *string;
TNODE *tree;
{
int cond;
assert(string != NULL);
if (tree == NULL)
{
printf("passed L36 if\n");
if (tree = (TNODE *)calloc(1, sizeof(TNODE)))
{
printf("passed L38 if\n");
tree->contents = strdup(string);
tree->count = 1;
}
else {
printf("didnt passed L38 if\n");
}
}
else
{
printf("didnt passed L36 if\n");
cond = strcmp(string, tree->contents);
if (cond < 0) {
printf("passed L47 if\n");
tree->left = install(string, tree->left);
}
else if (cond == 0) {
printf("passed L49 if\n");
tree->count++;
}
else {
printf("didnt passed L47 and L49 if\n");
tree->right = install(string, tree->right);
}
}
return (tree);
}
char *
getword(ioptr)
FILE *ioptr;
{
static char string[1024];
char *ptr = string;
register int c;
assert(ioptr != NULL);
for (;;)
{
c = getc(ioptr);
if (c == EOF) {
printf("passed L67 if\n");
if (ptr == string) {
printf("passed L68 if\n");
return (NULL);
}
else {
printf("didnt passed L68 if\n");
break;
}
}
else printf("didnt passed L67 if\n");
if (!MapAllowed[c]) {
printf("passed L72 if\n");
if (ptr == string) {
printf("passed L73 if\n");
continue;
}
else {
printf("didnt passed L73 if\n");
break;
}
}
else printf("didnt passed L72 if\n");
*ptr++ = MapAllowed[c];
}
*ptr = '\0';
return (string);
}
void tokens(ioptr) FILE *ioptr;
{
TNODE *root = NULL;
char *s;
assert(ioptr != NULL);
while (s = getword(ioptr)) {
printf("passed L88 while\n");
root = install(s, root);
}
printf("got out of L88 while\n");
treeprint(root);
}
int main(argc, argv)
int argc;
char **argv;
{
int c, errcnt = 0;
extern char *optarg;
while ((c = getopt(argc, argv, "ac:im:")) != EOF) {
printf("passed L98 while\n");
switch (c)
{
case 'a':
printf("passed L101 switch\n");
Alpha = 0;
break;
case 'c':
printf("passed L102 switch\n");
while (*optarg)
{
printf("passed L103 while\n");
MapAllowed[*optarg] = *optarg;
optarg++;
}
printf("got out of L103 while\n");
break;
case 'i':
printf("passed L109 switch\n");
Ignore = 1;
break;
case 'm':
printf("passed L110 switch\n");
Mincount = atoi(optarg);
break;
default:
errcnt++;
}
}
printf("got out of L98 while\n");
if (errcnt)
{
printf("passed L113 if\n");
fprintf(stderr, "Usage: %s [-i] [-c chars] [-m count]\n",
*argv);
return (1);
}
else {
printf("didnt passed L113 if\n");
}
for (c = 'a'; c <= 'z'; c++)
MapAllowed[c] = c;
for (c = 'A'; c <= 'Z'; c++)
MapAllowed[c] = Ignore ? c - 'A' + 'a' : c;
if (!Alpha) {
printf("passed L123 if\n");
for (c = '0'; c <= '9'; c++) MapAllowed[c] = c;
}
else {
printf("didnt passed L123 if\n");
}
tokens(stdin);
return (0);
}
```