Skip to content

Commit

Permalink
feat: update course_definition
Browse files Browse the repository at this point in the history
update import aliases to use camelCase
  • Loading branch information
ryan-gang committed May 24, 2024
1 parent ef7409a commit 9d723e7
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 70 deletions.
6 changes: 3 additions & 3 deletions internal/stages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"regexp"
"testing"

tester_utils_testing "github.com/codecrafters-io/tester-utils/testing"
testerUtilsTesting "github.com/codecrafters-io/tester-utils/testing"
)

func TestStages(t *testing.T) {
os.Setenv("CODECRAFTERS_RANDOM_SEED", "1234567890")

testCases := map[string]tester_utils_testing.TesterOutputTestCase{
testCases := map[string]testerUtilsTesting.TesterOutputTestCase{
"base_stages_pass": {
UntilStageSlug: "ip1",
CodePath: "./test_helpers/bash",
Expand All @@ -28,7 +28,7 @@ func TestStages(t *testing.T) {
},
}

tester_utils_testing.TestTesterOutput(t, testerDefinition, testCases)
testerUtilsTesting.TestTesterOutput(t, testerDefinition, testCases)
}

func normalizeTesterOutput(testerOutput []byte) []byte {
Expand Down
145 changes: 80 additions & 65 deletions internal/test_helpers/course_definition.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ short_name: "Shell"
release_status: "alpha"

description_md: |-
A shell is a command-line interpreter that provides a user interface for interacting with the operating system. In this challenge, you'll build your own shell capable of interpreting and executing basic commands, handling input/output redirection, and managing processes.
A shell is a command-line interface that executes commands and manages processes. In this challenge, you'll build your own
[POSIX compliant](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html) shell that's capable of interpreting
shell commands, running external programs and built-in commands like `cd`, `pwd`, `echo` and more.
Along the way, you'll learn about process creation and management, system calls, and the inner workings of a Unix-like operating system.
Along the way, you'll learn about REPLs, shell command parsing, built-in commands, and more.
short_description_md: |-
Learn about system calls, process control, and more.
Learn about parsing shell commands, executing programs and more
completion_percentage: 50
completion_percentage: 20

languages:
- slug: "go"
Expand Down Expand Up @@ -46,144 +48,157 @@ extensions:
stages:
- slug: "oo8"
name: "Shell Prompt"
name: "Print a prompt"
difficulty: very_easy
description_md: |-
In this stage, you'll implement the most basic shell functionality.
A shell prompt is the user interface for your shell, where users can type and execute commands. Your task is to make your shell print a `$` character and wait for user input. The shell should not exit after printing the prompt but continue to wait for commands.
In this stage, you'll implement printing a shell prompt (`$ `) and waiting for user input.
### Tests
The tester will execute your program like this:
```bash
> ./myshell
./your_shell.sh
```
If your shell prints the `$` prompt and waits for input, you'll pass this stage. Ensure that the shell does not exit immediately after printing the prompt.
The tester will then check whether your shell prints the `$ ` prompt and waits for user input.
### Notes
- The prompt has two characters: `$`, and a space after it.
- Your program must not exit after printing `$ `, it should wait for user input.
- We'll handle reading commands and executing them in later stages, this stage only deals with printing the prompt.
marketing_md: |-
In this stage, you'll implement printing the shell prompt and waiting for user input.
In this stage, you'll implement printing the shell prompt and waiting for user input.
- slug: "cz2"
name: "Missing Command"
name: "Handle missing commands"
difficulty: easy
description_md: |-
In this stage, you'll implement the basic command handling for your shell.
When a user enters a command that is not recognized by the shell, the program should print `<command>: command not found`. This is a common feature in most shells, providing feedback to the user when they attempt to execute an invalid command.
In this stage, you'll implement support for handling missing commands in your shell.
### Tests
The tester will execute your program like this:
```bash
> ./myshell
./your_shell.sh
```
It will then send the following command to your shell:
```bash
$ nonexistent
nonexistent: command not found
```
If your shell prints `<command>: command not found` for an unrecognized command, you'll pass this stage. Ensure that the shell does not exit immediately after printing the response.
The tester will check whether your shell prints `<command_name>: command not found` for an unrecognized command.
### Notes
- We will only pass commands that don't exist, you don't need to worry about finding the command in the system's PATH in this stage.
- We won't test whether the prompt is printed again, only that the correct message is printed to stdout.
- The command name will be a random string (like `missing_command_234`), so the response can't be hardcoded.
- We'll handle executing "valid" commands like `echo`, `cd` etc. in later stages, this stage only deals with unrecognized commands.
- In this stage it's okay if your program exits soon after printing the `<command_name>: command not found` message. In later stages
we'll check for a REPL (Read-Eval-Print Loop), i.e. whether the shell prints a new prompt after processing each command.
marketing_md: |-
In this stage, you'll implement handling unrecognized commands in your shell.
- slug: "ff0"
name: "REPL"
difficulty: medium
description_md: |-
In this stage, you'll implement a REPL (Read-Eval-Print Loop) for your shell.
In this stage, you'll implement a [REPL (Read-Eval-Print Loop)](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop).
A REPL is an interactive loop that reads user input, evaluates it, prints the result, and then waits for the next input. Your task is to ensure that your shell can handle multiple commands in sequence, responding with `<command>: command not found` for each unrecognized command, without exiting after processing a command.
A REPL is an interactive loop that reads user input, evaluates it, prints the result, and then waits for the next input.
### Tests
The tester will execute your program like this:
```bash
> ./myshell
./your_shell.sh
```
It will then send a series of commands to your shell:
```bash
$ invalid_command_1
invalid_command_1: command not found
$ invalid_command_2
invalid_command_2: command not found
$ invalid_command_3
invalid_command_3: command not found
$
```
The tester will send multiple commands, each time checking if `<command>: command not found` is printed to stdout. The program should not exit after processing these commands.
After each command, the tester will check if `<command_name>: command not found` is printed, and whether a prompt is printed for the next command.
### Notes
- Ensure that the shell remains running after processing each command.
- The REPL should correctly handle multiple commands in sequence.
- The exact number of commands sent and the command names will be random.
- Just like the previous stages, all commands will be invalid commands, so the response will always be `<command_name>: command not found`.
marketing_md: |-
In this stage, you'll implement a Read-Eval-Print Loop (REPL) for your shell.
In this stage, you'll implement a REPL (Read-Eval-Print Loop) for your shell.
- slug: "pn5"
name: "The Exit Built-in"
name: "The exit built-in"
difficulty: easy
description_md: |-
In this stage, you'll implement the `exit` built-in command for your shell.
When the `exit` command is received, your shell should exit gracefully with an exit code of 0. This allows users to close the shell properly. Your task is to handle the `exit` command while continuing to respond to other commands as before.
In this stage, you'll implement the [`exit` built-in](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#exit).
### Tests
The tester will execute your program like this:
```bash
> ./myshell
./your_shell.sh
```
It'll then send an invalid command to your shell, followed by the `exit` command:
```bash
$ invalid_command_1
invalid_command_1: command not found
$ exit 0
```
The tester will issue two unrecognized commands and check for the correct "command not found" responses. Then, the `exit` command will be issued, and the program should exit with code 0.
After issuing the `exit 0` command, the tester will verify whether your program terminates with [code/status](https://en.wikipedia.org/wiki/Exit_status) 0.
### Notes
- Ensure that the `exit` command causes the shell to exit with code 0.
- The shell should continue to handle other commands as usual until `exit` is received.
- The tester will always pass in `0` as the argument to the `exit` command.
marketing_md: |-
In this stage, you'll implement the `exit` built-in command for your shell.
- slug: "iz3"
name: "The Echo Built-in"
name: "The echo built-in"
difficulty: medium
description_md: |-
In this stage, you'll implement the `echo` built-in command for your shell.
When the `echo` command is received, your shell should print the rest of the line to stdout. This command is useful for displaying text and is a common feature in most shells. Make sure to handle the `echo` command within your shell, rather than executing an external `echo` binary.
In this stage, you'll implement the [`echo`](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html) built-in.
### Tests
The tester will execute your program like this:
```bash
> ./myshell
$ echo pineapple, apple
pineapple, apple
$ echo banana, pear, mango
banana, pear, mango
$ echo hello world
hello world
./your_shell.sh
```
The tester will check if the `echo` command correctly prints the provided text to stdout.
It'll then send a series of `echo` commands to your shell:
### Notes
```bash
$ echo hello world
hello world
$ echo pineapple strawberry
pineapple apple
```
- Ensure that the `echo` command prints the rest of the line to stdout.
- Prevent your shell from shelling out to an external `echo` binary.
- The output should exactly match the input text following the `echo` command.
After each command, the tester will check if the `echo` command correctly prints the provided text back.
marketing_md: |-
In this stage, you'll implement the `echo` built-in command for your shell.
- slug: "ez5"
name: "The Type Built-in"
name: "The type built-in: built-ins"
difficulty: medium
description_md: |-
In this stage, you'll implement the `type` built-in command for your shell.
Expand All @@ -195,7 +210,7 @@ stages:
The tester will execute your program like this:
```bash
> ./myshell
./your_shell.sh
$ type echo
echo is a shell built-in
$ type exit
Expand All @@ -217,7 +232,7 @@ stages:
In this stage, you'll implement the `type` built-in command for your shell.
- slug: "mg5"
name: "The Type Built-in - 2"
name: "The type built-in: executable files"
difficulty: hard
description_md: |-
In this stage, you'll enhance the `type` built-in command to search for executable files using the PATH environment variable.
Expand All @@ -229,7 +244,7 @@ stages:
The tester will execute your program like this:
```bash
> ./myshell
./your_shell.sh
$ type ls
/usr/bin/ls
$ type abcd
Expand Down Expand Up @@ -261,7 +276,7 @@ stages:
The tester will execute your program like this:
# ToDo: Update test
```bash
> ./myshell
./your_shell.sh
$ mkdir -p /tmp/test1/test2
$ touch /tmp/test1/test2/testing
$ ls /tmp/test1/test2
Expand All @@ -278,7 +293,7 @@ stages:
- slug: "ei0"
primary_extension_slug: "navigation"
name: "The PWD builtin"
name: "The pwd built-in"
difficulty: easy
description_md: |-
In this stage, you'll implement the `pwd` built-in command for your shell.
Expand All @@ -290,7 +305,7 @@ stages:
The tester will execute your program like this:
```bash
$ ./myshell
./your_shell.sh
$ pwd
/path/to/current/directory
```
Expand All @@ -305,7 +320,7 @@ stages:
- slug: "ra6"
primary_extension_slug: "navigation"
name: "The CD built-in: Absolute Paths"
name: "The cd built-in: Absolute paths"
difficulty: medium
description_md: |-
In this stage, you'll implement the `cd` built-in command to handle absolute paths for your shell.
Expand All @@ -317,7 +332,7 @@ stages:
The tester will execute your program like this:
```bash
$ ./myshell
./your_shell.sh
$ cd /usr/local/bin
$ pwd
/usr/local/bin
Expand All @@ -337,7 +352,7 @@ stages:
- slug: "gq9"
primary_extension_slug: "navigation"
name: "The CD built-in: Relative Paths"
name: "The cd built-in: Relative paths"
difficulty: hard
description_md: |-
In this stage, you'll implement the `cd` built-in command to handle relative paths for your shell.
Expand All @@ -349,7 +364,7 @@ stages:
The tester will execute your program like this:
```bash
$ ./myshell
./your_shell.sh
$ cd /usr
$ pwd
/usr
Expand All @@ -375,7 +390,7 @@ stages:
- slug: "gp4"
primary_extension_slug: "navigation"
name: "The CD built-in: HOME"
name: "The cd built-in: Home directory"
difficulty: medium
description_md: |-
In this stage, you'll implement the `cd` built-in command to handle the `~` character for your shell.
Expand All @@ -387,7 +402,7 @@ stages:
The tester will execute your program like this:
```bash
$ ./myshell
./your_shell.sh
$ cd /usr/local/bin
$ pwd
/usr/local/bin
Expand All @@ -404,4 +419,4 @@ stages:
- The `pwd` command will be used to verify the current working directory after using `cd ~`.
- The home directory is typically specified by the `HOME` environment variable.
marketing_md: |-
In this stage, you'll implement the ability for your shell to run the `cd` built-in command with the `HOME` directory.
In this stage, you'll implement the ability for your shell to run the `cd` built-in command with the `HOME` directory.
4 changes: 2 additions & 2 deletions internal/tester_definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package internal
import (
"testing"

tester_utils_testing "github.com/codecrafters-io/tester-utils/testing"
testerUtilsTesting "github.com/codecrafters-io/tester-utils/testing"
)

func TestStagesMatchYAML(t *testing.T) {
tester_utils_testing.ValidateTesterDefinitionAgainstYAML(t, testerDefinition, "test_helpers/course_definition.yml")
testerUtilsTesting.ValidateTesterDefinitionAgainstYAML(t, testerDefinition, "test_helpers/course_definition.yml")
}

0 comments on commit 9d723e7

Please sign in to comment.