# Snowcast Autograder Test Documentation This document provides a description of what each test performs. # Important notes For each test, we try to note the following requirements for each test to run: - **Stdin**: What commands the tester will send to your program on stdin (as if the user entered a key on the keyboard). (For example, the `q` command.) - **Stdout**: What output the tester expects you to print on stdout (eg. `The server has N stations`) - What Snowcast packets the server will send to your program, and what packets the tester expects to receive In all cases, the formats for what the tester expects are defined by the [**Snowcast specification**](https://hackmd.io/@csci1680/snowcast-spec). # Control Tests ## Startup And Connecting ### TestConnectsToServer Checks that the control can connect to the server and send a `HELLO` message to the server. ### TestCompletesHandshake **Stdin**: None **Stdout**: Reads `The server has N stations` on stdout Checks that the the control receives and handles the `WELCOME` reply from the server after the control sends a `HELLO` message. This test passes if the control is able to print out the number of stations. ### TestMultipleWelcomesFails **Stdin**: None **Stdout**: None Checks that the control disconnects from the server if the server sends multiple `WELCOME` replies. ### TestNoWelcomeFails **Stdin**: None **Stdout**: None Checks that the control closes the connection to the server if the server does not respond with a `WELCOME` 100ms after the control sends a `HELLO`. ## Handling Partial Messages ### TestPartialWelcomeTimeoutFails **Stdin**: None **Stdout**: None Checks that control terminates its connection to the server if the server does not receive a complete `WELCOME` message. This test waits for the control to send a `HELLO`, and then responds with only the first few bytes a of a `WELCOME` reply. The control is expected to to terminate its connection to server after 100ms and not receiving the complete `WELCOME`. ### TestSplitWelcomeSucceeds1 **Stdin**: None **Stdout**: Expects `The server has N stations` Checks that the control can successfully receive a `WELCOME` message from the server that is sent across two packets. This test waits for the control to send a `HELLO`, and then the test server responds with the first half of the `WELCOME` message, waits some time, and then sends the final half of the `WELCOME` message to the control. ### TestSplitWelcomeSucceeds2 **Stdin**: None **Stdout**: Expects `The server has N stations` Checks that the control can successfully receive a `WELCOME` message from the server that is sent across multiple packets. This test waits for the control to send a `HELLO`, and then the test server responds with packets each containing one byte of the `WELCOME` reply, with some delay between each packet. ### TestPartialAnnounceTimeoutFails **Stdin**: Sets a station **Stdout**: None Checks that the control closes its connection to the server if the control receives part of the `ANNOUNCE` message and does not receive the remainder of the `ANNOUNCE` message within 100ms of receiving the first part. ### TestSplitAnnounceSucceeds1 **Stdin**: Sets a station **Stdout**: Expects `New song announced: <song name>` Checks that the control can successfully receive an `ANNOUNCE` message from the server that is sent across two packets. The test server responds with the first half of the `ANNOUNCE` message, waits some time, and then sends the final half of the `ANNOUNCE` message to the control. ### TestSplitAnnounceSucceeds2 **Stdin**: Sets a station **Stdout**: Expects `New song announced: <song name>` Checks that the control can successfully receive a `ANNOUNCE` message from the server that is sent across multiple packets. The test server responds with packets each containing one byte of the `ANNOUNCE` reply, with some delay between each packet. ## Message Formatting ### TestSetStationFormat **Stdin**: Sets a station **Stdout**: None Checks that the control sends `SET_STATION` commands in the correct format. ### TestExitsOnInvalidCommand **Stdin**: None **Stdout**: Expects `The server has N stations` on to verify startup Checks that the control terminates if the server sends an invalid command message to the control. ### TestExitsOnInvalidReplyType **Stdin**: None **Stdout**: None Checks that the control terminates its connection with the server if the server responds with an invalid reply type to the control (i.e some unknown reply type). ## Miscellaneous Functionality ### TestPrintsAnnounce1 **Stdin**: Sets a station **Stdout**: Expects `New song announced: <song name>` Checks that the control can print a single `ANNOUNCE` message received from the server. ### TestPrintsAnnounce2 **Stdin**: Sets a station **Stdout**: Expects `New song announced: <song name>` Checks that the control can continuously print a `ANNOUNCE` messages received from the server. This test sends 10 `ANNOUNCE` messages to the control and checks that the control can print all 10 `ANNOUNCE` messages. ### TestAnnounceBeforeSetStationFails **Stdin**: None **Stdout**: None Checks that the control terminates its connection with the server if the control receives an `ANNOUNCE` message from the server before sending a `SET_STATION` message to the server. ### TestSetStationInvalidCommandResponseFails **Stdin**: Sets station **Stdout**: None Checks that the control terminates its connection to the server if the server responds with the incorrect response type (i.e responding with a `WELCOME` instead of an `ANNOUNCE`) ### TestQuitsCleanly **Stdin**: `q` command **Stdout**: None Checks that the control can exit cleanly when the user inputs the quit command to the control CLI. ## Server Tests ### TestNoStationsFails **Stdin**: None **Stdout**: None Checks that the server fails to start if no stations were provided ### TestAcceptsClientConnection **Stdin**: None **Stdout**: None Checks that the server does not fail when accepting a single connection. ### TestTimesOutConnectionWithNoHello **Stdin**: None **Stdout**: None Checks that the server closes a client connection when the client does not send a `HELLO` message within 100ms of connecting to the server. ### TestCompletesHandshake **Stdin**: None **Stdout**: None Checks that the server responds with a `WELCOME` response, completing the handshake, when the client sends a `HELLO` message. ### TestMultipleHellosFails **Stdin**: None **Stdout**: None Checks that the server terminate a client connection if the client sends multiple `HELLO` messages. ### TestServerSurvivesClientDisconnect **Stdin**: `p <file>` command **Stdout**: None, but must read station list from file Checks that the server does not terminate if a client disconnects. ### TestPartialHelloTimeoutFails **Stdin**: None **Stdout**: None Checks that server terminates a client connection if the server does not receive a complete `HELLO` message. This test sends only the first few bytes of the `HELLO` message to the server and the server is expected to terminate the client after not receiving the full `HELLO` message with 100ms to receiving the first few bytes. ### TestSplitHelloSucceeds1 **Stdin**: None **Stdout**: None Checks that the server can successfully accept a `HELLO` message from the client that is sent across multiple packets. This test sends the first few bytes of the `HELLO` message to the server, waits some time, and then sends the final bytes of the `HELLO` message to the server. ### TestSplitHelloSucceeds2 **Stdin**: None **Stdout**: None Checks that the server can successfully accept a `HELLO` message from the client that is sent across multiple packets. This test sends each byte of the `HELLO` message to the server in a separate packet, with some delay between each of the sends. ### TestPartialSetStationTimeoutFails **Stdin**: None **Stdout**: None Checks that server terminates a client connection if the server does not receive a complete `SET_STATION` message. This test sends only the first few bytes of the `SET_STATION` message to the server and the server is expected to terminate the client after not receiving the full `SET_STATION` message with 100ms to receiving the first few bytes. ### TestSplitSetStationSucceeds1 **Stdin**: None **Stdout**: None Checks that the server can successfully accept a `SET_STATION` message from the client that is sent across multiple packets. This test sends the first few bytes of the `SET_STATION` message to the server, waits some time, and then sends the final bytes of the `SET_STATION` message to the server. ### TestSplitSetStationSucceeds2 **Stdin**: None **Stdout**: None Checks that the server can successfully accept a `SET_STATION` message from the client that is sent across multiple packets. This test sends each byte of the `SET_STATION` message to the server in a separate packet, with some delay between each of the sends. ### TestSetStationBeforeHelloFails **Stdin**: None **Stdout**: None Checks that the server terminates a client connection if the client sends a `SET_STATION` message before a `HELLO` message. ### TestSetStationSucceeds **Stdin**: None **Stdout**: None Sends `SetStation` message to the server and checks to make sure the correct `Announce` is received. ### TestSupportsMultipleStations **Stdin**: `p <file>` command **Stdout**: None, but must read station list from file Checks that the server can support multiple stations. This test sets up the server with multiple stations and then iterates over each file provided for a station. For each file, the test does the following: - send a `SET_STATION` message to the server for each station and assert that the server responds with a corresponding `ANNOUNCE`. - checks that the test client is placed with the correct station in the server. ### TestStreamsWithoutReadingEntireFile **Stdin**: `p <file>` command **Stdout**: None, but must read station list from file Checks that file data is streamed by reading a fixed number of bytes at a time instead of reading the entire file into memory at once. To ensure this behavior, this test uses `/dev/urandom` and `/dev/zero` as files for the stations. ### TestInvalidStationFails **Stdin**: None **Stdout**: None Checks that the server terminates a client connection if the client sends a `SET_STATION` message to the server that contains an invalid station number. ### TestAcceptsMultipleConnections **Stdin**: `p <file>` command **Stdout**: None, but must read station list from file Checks that the server can handle multiple connections with each connection have different stations. This test makes several connections from different client, prints the station list to a file, and verifies that each client is listed on the correct station. ### TestAcceptsMultipleConnectionsRegardlessOfStation **Stdin**: None **Stdout**: None Checks that the server can handle multiple connections with each connection have different stations. This test performs the same check as `TestAcceptsMultipleConnections`, except the connections are verified only by looking at the set of sockets used by the `snowcast_server` process--there is no verification that clients are joined to the correct station. **Note**: This test is designed to test a strict subset of the functionality in `TestAcceptsMultipleConnections`. If you are failing this test but passing `TestAcceptsMultipleConnections`, don't worry--we'll adjust manually. ### TestStreamRateSingle **Stdin**: None **Stdout**: None Checks that the server's stream rate is 16KiB/s for a single connection listening to one station. ### TestStreamRateMultipleOneStation **Stdin**: None **Stdout**: None Checks that the server's stream rate is 16KiB/s for a multiple connections listening to one station. ### TestStreamRateMultipleStations **Stdin**: None **Stdout**: None Checks that the server's stream rate is 16KiB/s for a multiple connections listening to different stations. ### TestStreamsWithNoListeners **Stdin**: None **Stdout**: None This test attempts to verify that the station continues playing music when no clients are joined to the station. To do this, the test starts the server and waits >1s before joining a client. When the client first receives listener data, the data must not match the beginning of the file. **Note**: The functionality tested here is generally straightforward manually, but quite difficult to test programmatically. We will manually review test failures to check for false negatives, and adjust accordingly. If you are failing this test, ask yourself: "Is the station still reading the file when no clients are connected?" If your design for stations does this, you will get credit. ### TestServerClosesConnectionOnInvalidCommandType **Stdin**: None **Stdout**: None Checks that the server terminates a client connection if the client sends a command with an unrecognized command type.