ECE 2524 - Word Frequency Count: Part 2

ECE 2524

Introduction to Unix for Engineers

Word Frequency Count: Part 2

Last modified

Background

Both user’s code should contain a barebones implementation of the getopt loop (see example source ) that parses -k and -h options.

  1. Each group member implement a specific feature in your local code.

    user1: add error checking to the strtol call (see EXAMPLE section of man page for strtol). Only set the variable containing the value for k if a valid integer was present in the option argument for -k. If no argument was given, or the argument did not contain an integer then print an error to standard error and exit.

    $ ./wordfreq -k
    ./wordfreq: option requires an argument -- 'k' 
    Usage: wordfreq [-h] [-k N]
    $ ./wordfreq -k five
    No digits were found
    Usage: wordfreq [-h] [-k N]

    Note that the first line of output shown is generated automatically by getopt if you configured it properly i.e. configuration string should be “k:”.

    user2: add a -r option that when present will cause the program to print the word list in reverse frequency order (least frequently used words first).

    $ ./wordfreq -r

    The API for the analytics library has been updated to reflect support for sort options. The opt paramter to sort_counted_words can be set to either AMAP_SORT_ASCENDING or AMAP_SORT_DESCENDING for sorting in ascending or descending order, respectively.

    Note: user2 be sure to update the Usage message to include the -r option:

    $ ./wordfreq -h
    Usage: wordfreq [-hr] [-k N]
  2. Each group member add/commit and push changes to your own origin

  3. user1 pull changes from user2’s remote:

     user1@local $ git pull user2 master
    

    ideally git should merge the changes automatically. If you receive a message about a conflict in main.c you will need to open that file in an editor and perform a manual merge.

  4. Once user1 has successfully merged, push the merged code back to your own origin.

    user1@local $ git push origin master
    
  5. user2 can now pull from upstream to update their local copy with the merged code

    user2@local $ git pull upstream master

Merge conflicts

Because both people will be modifying the top part of main where veraibles are declared user1 will likely be notified of a conflic in main.c when they pull from user2’s remote. When this occurs, open main.c in your text editor to see what the problem was, you will see something like the following:

int main(int argc, char *argv[]) {
    long int nlimit=10, val;
    word_list_t wl;
    word_map_t wm;
<<<<<<< HEAD
    int opt;
    char *endptr;
=======
    int opt, sort_opt = AMAP_SORT_DESCENDING;
>>>>>>> 8ec39be37ec486ea8670ceb57fb70e4fa6b0b3aa

    /* remainder of implementation */

}

You only need to concern yourselfe with code between the lines starting with <<<<<<< and >>>>>>>, lines outside this region were merged automatically by git. In the preceding example git is telling me that the lines

    int opt;
    char *endptr;

in user1’s HEAD (the current state of your code when you performed the merge), and the line

    int opt, sort_opt = AMAP_SORT_DESCENDING;

which were in the remote user’s code (the 40 character hexadecimal string is the commit id of the particular commit of the merged changes), are in conflict. In the example above, user1 has added the char *endptr; declaration which is used for the strtol error checking while user2 has added the sort_opt declaration used for the sort option. Both are needed, so in this case I could edit the file to look like

int main(int argc, char *argv[]) {
    long int nlimit=10, val;
    word_list_t wl;
    word_map_t wm;
    int opt;
    char *endptr;
    int sort_opt = AMAP_SORT_DESCENDING;

    /* remainder of implementation */

}

The result should be the complete, merged source file. Notably, you must manually remove the three lines added by git (starting with >>>>>>>, <<<<<<< and =======) so that git knows the conflict has been resolved.

Once you have resoled a merge conflict by making the necessary changes to the associated files be sure to compile the program to make sure it works as expected, then add and commit the merged file:

$ git add main.c
$ git commit

Because the change is part of a merge git will populate the commit message with text about the merge. In most cases you will probably just leave the generated message as is.

Submission

The source files should exist in their own git repository, if you change to the directory containing your source files and run ls -a you should see a directory named .git. If not, run git init to initialize a git repository in the current directory. You should only run git init once for each new project.

Push your git repository to the remote at git@ece2524.ece.vt.edu:USER/wordfreq.git where USER is your git user name.

If you have initialized a new repo but have not added a remote yet:

$ git remote add origin git@ece2524.ece.vt.edu:USER/wordfreq.git

where is your git user name.

If you have already added a remote named origin, but the URL is incorrect, replace add with set-url in the above command. You can always check that remotes you have added by running git remote -v.

Remember, if this is the first time pushing to a new remote you need to specify a destination branch (usually `master`). Using the `-u` option will save this default destination for future pushes.

$ git push -u origin master

Testing

Feature repo path: features/wordfreq

The following features will be tested using cucumber:

@compile
Feature: Compile

  Background:
    Given I am working from a clean git clone to "wordfreq"
    And I cd to "wordfreq"
    
  Scenario: Clean Repo
    Then a file named "wordfreq" should not exist

  Scenario: Compile
    When I successfully run `clang -c -o main.o main.c`
    Then a file named "main.o" should exist
    When I successfully run `clang -o wordfreq -lanalytics main.o`
    Then a file named "wordfreq" should exist
@part2 @no-clobber
Feature: Command Line Arguments

  Background:
    Given I cd to "wordfreq"
    And a file named "fox.txt" with:
    """
    the quick brown fox jumped over the lazy cow.
    but the cow jumped over the moon!
    what does the fox say?
    
    """
    And a file named "numbers" with:
    """
    four two four one
    two four three three
    three four
    
    """

  Scenario: "-k option"
    When I run the shell command "./wordfreq -k 5 < fox.txt"
    Then its stdout should contain exactly 5 lines
    And its stdout lines should match:
    | ^\s*5\s+the$    |
    | ^\s*2\s+cow$    |
    | ^\s*2\s+fox$    |
    | ^\s*2\s+jumped$ |
    | ^\s*2\s+over$   |
    And the exit status should be 0

  Scenario: "-r option"
    When I run the shell command "./wordfreq -r < numbers"
    Then its stdout should contain exactly 4 lines
    And its stdout lines should match:
    | ^\s*1\s+one$   |
    | ^\s*2\s+two$   |
    | ^\s*3\s+three$ |
    | ^\s*4\s+four$  |
    And the exit status should be 0

  Scenario: "-r and -k options"
    When I run the shell command "./wordfreq -r -k 8 < fox.txt"
    Then its stdout should contain exactly 8 lines
    And its stdout lines should match:
    | ^\s*1\s+brown$ |
    | ^\s*1\s+but$   |
    | ^\s*1\s+does$  |
    | ^\s*1\s+lazy$  |
    | ^\s*1\s+moon$  |
    | ^\s*1\s+quick$ |
    | ^\s*1\s+say$   |
    | ^\s*1\s+what$  |
    And the exit status should be 0
@part2 @no-clobber
Feature: Command Help Options

  Background:
    Given I cd to "wordfreq"
    And a file named "numbers" with:
    """
    four two four one
    two four three three
    three four
    
    """

  Scenario: "-h option"
    When I run the shell command "./wordfreq -h"
    Then the exit status should be 0

  Scenario: "invalid option"
    When I run the shell command "./wordfreq -x < numbers"
    Then the exit status should not be 0
    And its stdout should contain exactly 0 lines
    And its stderr should contain at least 1 line
    And its stderr should contain at most 2 lines
    And its stderr should contain a line matching /^Usage: (?:\.\/)?wordfreq \[-hr\] \[-k N\]$/
@part2 @no-clobber
Feature: Collaboration

  Background:
    Given I cd to "wordfreq"

  Scenario: "Contributors"
    Then the git repo should have at least 2 contributors

You can run the tests manually with

$ cucumber /usr/share/features/wordfreq
when logged in to your shell account. This command assumes your current working directory is your project directory.