| NOTE: THE MIDTERM MARK WAS ACTUALLY RECORDED OUT OF 32, NOT 40 |
| Question | Mark |
| 1. Git, branch, merge [8 marks] | |
| 2. Bash and defensive programming [8 marks] | |
| 3. Bash scripting [8 marks] | |
| 4. Specifications [8 marks] | |
| 5. Life cycle models [8 marks] | |
| Exam Total [40 marks] |
Question 1: Git, branch, merge [8]
(i) Provide the exact sequence of git and bash commands necessary to enact the steps described below.
(ii) Identify the points where merge conflicts would need to be addressed, and which specific file(s) would be the source of conflict(s).
| The files in /src/core are: readme, layout.txt, makefile
numTypes.h, numTypes.cpp, data.h, data.cpp, hash.h, hash.cpp |
Sample Solution
(1) mkdir proj
cd proj
git init
(2) cp /src/core/*.h .
cp /src/core/*.cpp .
cp /src/core/makefile .
git add .
git commit -m "core content"
(3) git branch altData
git checkout altData
(4) vim hash.cpp newdata.cpp makefile
(5) git rm data.cpp
(6) git add .
git commit -m "first altData changes"
(7) git checkout master
(8) vim data.h
git add .
git commit -m "updated master data"
(9) git branch altTypes
git checkout altTypes
(10) vim data.h numTypes.h
git add .
git commit -m "first altTypes changes"
(11) git checkout master
(12) git merge altTypes [note: there is no conflict here since altTypes
was created after master's changes to data.h,
so it has only changed in one branch]
(13) vim makefile
git add .
git commit -m "updated master make"
(14) git merge altData [note: there is a merge conflict here in makefile,
since it has been altered in both branches]
|
Question 2: Bash and defensive programming [8]
In a recent lecture we discussed defensive programming and the desire to produce robust programs. Many of these issues are particularly relevant when creating bash scripts for administrative tasks.
For the bash script shown below, identify specific weaknesses from the point of view of robustness and defensive programming, and suggest approaches to address those weaknesses (you do not need to produce actual bash code to fix them). Sample runs of the script are also shown below.
Note: the "2> /dev/null" used below effectively suppresses stderr messages from command
#! /bin/bash
function menu()
{
echo "The available actions are:"
echo " H - display your home directory and total disk utilization"
echo " I - display system status information"
echo " L - list the current directory location and content"
echo " M - display this menu"
echo " S - display the storage space used for the current directory (and subdirectories)"
echo " Q - quit"
}
function info()
{
echo "Enter your command (any of H I L M Q S - M displays the full menu)"
read cmd
if [ $cmd = "H" ] ; then
echo "The disk utilization stats for account " $USER " (home directory " $HOME ") are:"
du -sh $HOME 2> /dev/null
elif [ $cmd = "S" ] ; then
echo "The disk storage stats for " $PWD " are:"
du -sh . 2> /dev/null
elif [ $cmd = "M" ] ; then
menu
elif [ $cmd = "L" ] ; then
echo "The contents of " $PWD " are:"
ls -aF
elif [ $cmd = "Q" ] ; then
echo "Bye!"
elif [ $cmd = "I" ] ; then
echo "The status of system " $HOSTNAME " is "
uptime
else
echo "Invalid command entered: " $cmd
fi
}
info
| Enter your command (any of H I L M Q S - M displays the full menu) H The disk utilization stats for account wesselsd (home directory /home/faculty/wesselsd ) are: 2.0G /home/faculty/wesselsd |
Sample SolutionLots of possible critiques here, some more important than others: - if user enters something like * then when it gets to the "Invalid command" output it actually displays the current directory contents, so either the user input should be sanitized or (at least) when displaying the variable it should be placed inside quotes (i.e. "$cmd") - to be more forgiving on input it should either accept both upper and lowercase commands or convert them all to a standard case before checking - redirecting some of the stderr output to /dev/null conceals potential problems from the user: the output should probably be captured and more appropriate messages delivered to the user as a result - the command output from other system commands are delivered to the user unfiltered, errors and all: it would probably be wise to capture/filter that - the prompts and error messages, and how to invoke menu, could be clearer - a retry/repeat option might be helpful, rather than making the user re-run the script - the script is entirely uncommented - a gui to better control interaction with the user might help |
Question 3: Bash scripting [8]
Write a complete and correct bash function named "gitmakes" that meets the following specifications:
gitmakes dir1 dir2 dir3 dir1 is the root of a git directory dir1/foo contains a makefile Error: dir2 is not an accessible directory dir3/subdir is the root of a git directory dir3/subdir contains a makefile dir3/sub/sub contains a makefile |
Sample Solution
# helper function to process a single directory
function gitex()
{
# bail out if no directory given (won't happen from gitmakes)
if [ $# -ne 1 ] ; then
echo "dir expected"
return 0
fi
# grab the directory name, error check, and process
local dir=$1
# process iff it is an accessible directory
if [ -d $dir ] && [ -r $dir ] && [ -x $dir ] ; then
# check for git repository
if [ -d "$dir"/.git ] ; then
echo "$dir is the root of a git repository"
fi
# check for makefile
if [ -f "$dir"/makefile ] ; then
echo "$dir contains a makefile"
fi
# recurse into any subdirectories
for subdir in "$dir"/* ; do
if [ -d $subdir ] ; then
gitex $subdir
fi
done
# give error messages for invalid/inaccessible directories
else
echo "Error: $dir is not an accessible directory"
fi
}
# gitmakes takes the list of directories and passes them one at a time to gitex
function gitmakes()
{
for dir in $@ ; do
gitex $dir
done
}
|
Question 4: Specifications [8]
Suppose we needed to come up with a set of non-functional specifications for a text-messaging service, and for future verification purposes we need quantifiable/measurable specifications.
Provide a set of example specifications covering:
Sample Solution
Lots of possibilities here, but they have to be specifications covering the
qualitative (not functional) aspects mentioned, and the specifications
you give must be measurable, e.g.
availability: the system cannot be unavailable more than 3 hours per month,
and never unavailable for more than 15 consecutive minutes
capacity: within the availability constraints above, the central servers
should be capable of processing 10,000 messages per minute
accessibility: within the capacity and availability constraints listed above,
the only acceptable reason for the system being unaccessible to the user
is a third-party network failure somewhere between the user and our servers
reliability: 99.9% of all messages sent per month should be received,
subject to the constraints listed above
data integrity: 99.9% of all messages received should arrive in an uncorrupted form
delivery speed: all messages received should arrive within 12 seconds of being sent,
subject to the constraints listed above
|
Question 5: Life cycle models [8]
A test-driven software development process works as follows:
(i) Describe circumstances under which this would be a worthwhile process to follow.
(ii) Discuss the advantages and disadvantages of this process compared to an agile development process.
Sample SolutionNote that, compared to an agile process, this new (to us) process is more focused on passing specific relevant/representative test cases provided for us by the client, rather than on more general feedback/direction/requirements. (The user isn't giving us requirements except in the form of test cases it must pass.) (In reality, the test-driven-development is often used as an internal process, where someone in the development team comes up with the sequence of test cases based on conversations with the user, and the rest of the dev team has to code to pass the latest test plus all the others.) In the form described, it is likely to be worthwhile when - the product is something that can be delivered bit by bit and still be useful (adding new functionality to what we've already built) - the client is good at providing representative test cases, but perhaps not so good at giving more generalized goals/feedback or a bigger picture - the developers are good at writing adaptable code, and modifying it to meet new objectives Advantages compared to agile: - the developers have very clear pass/fail targets for each new test, they aren't waiting for less predictable feedback from the user(s) - the individual development cycles are probably quicker in general, since the devs are coding just to one specific test rather than more generalized goals/objectives Disadvantages compared to agile: - the test-based nature is less suitable for generalized feedback, the client has to come up with test cases that demonstrate what they want, which the user might find challenging. - it might take more development cycles to arrive at what the user really wants compared to agile, simply because the number of tests needed to encapsulate all desired behaviour might be pretty large - as given, it assumes each test case is valid forever, whereas agile is more flexible, allowing the user to change their mind and toss out earlier ideas |