Takeaways

  • Become familiar with unit testing by implementing unit tests for an existing C++ project.
  • Practice using Git and GitLab to submit assignments.

Relevant Resources


Welcome to Doofenshmirtz Evil Inc.

There you are. Minding your own business. Just standing outside and waiting for the Eclipse of the Century.

In the distance, you hear the hum of a helicopter. Although it doesn’t quite sound like a helicopter. And it’s getting louder. You see a great shadow crawl across the Tri-State Area.

But it’s not the moon.1

Suddenly, a cartoonish, Mickey-Mouse-gloved claw reaches from the dark entity above. It scoops you up in one quick motion and yanks you off the ground.

“I saw your resume at the career fair” a voice says. “You didn’t give it to me, but I definitely saw it.”

The voice emerges from the shadows. A… man?2… approaches you with a look of pride.

“I’m just so happy you’ve decided to work for me…”

He pushes a button on a single-red-button remote. Nothing happens.

He looks at the button with disdain and presses it harder, faster. He hits the bottom of the remote. A cheesy thunder and lightning sound effect plays.

File Photo

“DOCTOR HEINZ DOOFENSHMIRTZ” he yells.

Timidly, he explains. “That’s my name. I’m Heinz Doofenshmirtz… It would have been better if the sound… well you get it.” He puts the remote down. “Welcome to Doofenshmirtz Evil Incorporated!” He pulls a cord and a Welcome banner unfurls, slowly dropping balloons and confetti.

“Alright, now that’s enough fun. We’re on a deadline!” he shouts and hurries over to a laptop. He returns and explains, “I need you to finish this decrypt-inator program, so that I can figure out when Perry the Platypus is going to arrive to foil my evil plan!”

You raise an eyebrow.

“You see, OWCA3 electronically transmits orders to their agents, which I can intercept with my intercept-inator! However, I can’t actually tell what they say because they’re encrypted. That’s why I need you to fix my decryptinator!”

You raise the other eyebrow. Both eyebrows are raised.

Decryption Description

Using his Intercept-inator, Dr. Doofenshmirtz is able to intercept transmissions sent from OWCA to its agents. Your job is to test and repair the C++ class that is responsible for decrypting those transmissions.

Each agent has a unique 3-digit ID that they use in to decrypt the messages meant for them. Each digit (1 through 5) corresponds to a numbered disk that performs a cryptographic operation.

So what are the disks for?

The OWCA decryptor contains 3 slots called rotors (labeled left, middle, right). Each rotor can accept one of 5 different disks (numbered 1 through 5). When a message is entered into the decryptor, it passes each character through each of the three rotors from left to right. Each rotor uses its assigned disk to partially decrypt the each letter, so that the output of the right rotor (the last rotor) is the original (plaintext) message.

You can find a description of the original decryption scheme here: https://sites.google.com/a/mst.edu/price/courses/cs-1570/hw/2015/fall/assignment-06.4

For the sake of security, OWCA modified the behavior of some of the disks. Below is a summary of how the OWCA decryption disks work.

Disk 1
f(ch) = (((ascii value of ch) + 3) % 26) + 65
Disk 2
f(ch) = (((ascii value of ch) + 5) % 26) + 65
Disk 3
Input letters map to output letters as follows:
  • A -> Y
  • B -> J
  • C -> T
  • D -> Z
  • E -> O
  • F -> G
  • G -> C
  • H -> L
  • I -> M
  • J -> A
  • K -> E
  • L -> K
  • M -> U
  • N -> H
  • O -> P
  • P -> X
  • Q -> S
  • R -> F
  • S -> W
  • T -> B
  • U -> D
  • V -> Q
  • W -> N
  • X -> V
  • Y -> R
  • Z -> I
Disk 4
Replaces
  • A with B and B with A
  • C with D and D with C
  • Y with Z and Z with Y
Disk 5
Replaces
  • A with Z and Z with A
  • B with Y and Y with B
  • C with X and X with C

Decryption Examples

Single Disks

We happen to have some example data that demonstrates how a rotors work when equipped with different disks. The table below shows how a single rotor (configured to use a specific disk) should decrypt a string. For example, if you have a rotor configured to use disk 1 and you feed it the characters (in order) KBLCMDNEOFPGQHRISJTKULVMWN, you should get the ABCDEFGHIJKLMNOPQRSTUVWXYZ as output.

Disk Number Input String Output String
1 KBLCMDNEOFPGQHRISJTKULVMWN ABCDEFGHIJKLMNOPQRSTUVWXYZ
2 IBJCKDLEMFNGOHPIQJRKSLTMUN ABCDEFGHIJKLMNOPQRSTUVWXYZ
3 JKWYMFANMPWLXZFJMMEYOJJGUJ ABCDEFGHIJKLMNOPQRSTUVWXYZ
4 BZEYHXKWNVQUTTWSZRCQFPIOLN ABCDEFGHIJKLMNOPQRSTUVWXYZ
5 ZZYYXXWWVVUUTTSSRRQQPPOONN ABCDEFGHIJKLMNOPQRSTUVWXYZ

Complete Messages

Additionally, we happen to have two example messages (encrypted) that decrypt to a known string. Each of these messages decrypt to THE_QUICK_BROWN_FOX_JUMPS_OVER_THE_LAZY_DOG for obvious reasons.

Disk Order Input String
1 2 3 UZJ_HVOCY_JFUQR_GBH_BRDJT_ZQCB_HRT_ARPM_EXU
1 2 4 KWR_YKYLE_NKYQQ_SFT_APFKP_RWHU_XEM_VGND_ELP
1 2 5 YSD_EWSHA_PMMYA_SPL_CHFCJ_DWTQ_NUO_HYBB_WXR

So how does each agent know their own disk order? An agent’s ID corresponds to their disk order. For example, Perry the Platypus’ agent ID is 315, so his disk order will be 3 1 5. Peter the Panda has ID 231, Pinky the Chihuahua has ID 341, and so on in that order. Fortunately, we aren’t concerned with this aspect of agent communication.


Your Task

You’ve been given a partially complete project. You are to do the following (in order):

  1. Complete the partially implemented unit tests in the project
  2. Fix the decryptor

Refer to this assignment’s rubric for further description of point values for completed tasks.

Compiling

Boost’s unit test framework does not live in a place where g++ ordinarily looks for libraries. That means that we have to tell g++ about it. The compile command you will use is…

g++ *.cpp -lboost_unit_test_framework

The -lboost_unit_test_framework tells g++ that we’re going to need to link against the unit test framework.

You can also use make to build the program. The starter code comes with a simple Makefile that should do the trick.

Test Coverage

There’s a script in the project called show-coverage that will compile everything, run the unit tests, and show the code coverage of the test suite. Make sure that your tests achieve 100% coverage for funcs.cpp and rotor.cpp.

show-coverage will also create two files: funcs.cpp.coverage and rotor.cpp.coverage. You can read those to see how many times each statement in the program was run. If a line was never run, it will be marked with a bunch of pound signs (#######) to get your attention.

Other Notes

  • Try to keep your lines under 80 columns wide. Don’t go too crazy, though. If breaking lines makes your code look ridiculous, then go over 80 lines. If you have a question about style, ask your instructor.
  • Use your unit tests to help you find and fix the error(s) in the decryption code.
  • Read the code’s documentation. It will be useful.
  • Test private member functions through calls to public member functions. Do not worry about calling private member functions directly.
  • The starter code will compile warning- and error-free as it is. However, it will not decrypt messages properly until you fix it.
  • If it’s helpful, you can still use cout to help debug your code. Be sure to remove those statements before you submit.
  • Notice that Rotor::decrypt accepts a char as a parameter and returns a char. You can’t just pass a string to it… Maybe you could use a loop and the bracket ([]) operator to go char by char?
  • If the starter code neglects a test case, you’re welcome to add additional tests. However, make sure you implement the stubs that are already provided. Also, comment any additional test cases and explain why they were necessary.
  • You’re welcome to use WARN or REQUIRE level assertions if you feel that they’re necessary. If you decide to, be sure to include a comment explaining why CHECK wasn’t sufficient.
  • Do not commit any of the *.coverage files or compiled files. Your assignments will be compiled and run as part of the grading process.
  • Your assignment must compile and run with g++ on campus Linux machines (rc__xcs213.managed.mst.edu). If you choose to develop on another platform, make sure that it works on the campus Linux machines before you submit.

Further Details

Point Value

This assignment is worth 50 points. It will be graded according to the following rubric:

Feature Points Possible Mostly or completely incorrect (0% of points possible) Needs improvement (50% of points possible) Adequate, but still some deficiencies (75% of points possible) Mostly or completely correct (100% of points possible)
Correctly tested functionality of disk 1 3 0 / 3 1 / 3 3 / 3
Correctly tested functionality of disk 2 3 0 / 3 1 / 3 3 / 3
Correctly tested functionality of disk 3 3 0 / 3 1 / 3 3 / 3
Correctly tested functionality of disk 4 3 0 / 3 1 / 3 3 / 3
Correctly tested functionality of disk 5 3 0 / 3 1 / 3 3 / 3
Correctly tested decryption of messages 5 0 / 5 2 / 5 5 / 5
Successfully repaired decryption and passed all correctly implemented unit tests 5 0 / 5 2 / 5 3 / 5 5 / 5
Submitted code properly with Git and GitLab (reflection.md exists and is coherent, commit messages are meaningful, no superfluous files, etc.) 10 0 / 10 5 / 10 7 / 10 10 / 10
Program compiles and links without errors or warnings 5 0 / 5 5 / 5
Achieved 100% coverage for funcs.cpp and rotor.cpp 5 0 / 5 2 / 5 3 / 5 5 / 5
Code review (proper style, sufficient comments, etc.) 5 0 / 5 2 / 5 3 / 5 5 / 5
Points possible 50        

Each cell indicates how many points out of the available points will be awarded for that feature (row) and assessment level (column).

Cells marked -- cannot be achieved. For example, no partial credit will be awarded for code that has compiler errors or warnings. Points for that feature are all-or-nothing.

Submission

Deadline

11:59:59 PM CDT – Tuesday, August 29, 2017

Submission Procedure

Refer to the assignment submission page on the course website for details on submitting your code to GitLab.

Grading Procedure

When grading your assignment, the following series of commands will be used to compile your code

# Assuming that we're at the top directory of your project
$ make
$ ./test_decrypt
$ ./show-coverage

Your code must compile with this command on the campus Linux machines. The show-coverage script will be run to check code coverage. Do not modify show-coverage.

  1. Or so you think. You done burnt up your retinas looking at the sun. 

  2. Possibly a bird. Again with the looking-at-the-sun business. 

  3. The Organization without a Cool Acronym employs agents to foil the plots of evil scientists around the world. 

  4. The author of that specification is a fellow mad scientist and former colleague of Dr. Doofenshmirtz. They had a falling out. Legend has it that it all started with a heated argument about cows.