# How is test input passed to shell program in testing environment?

**URL:** <https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430>\
**Category:** Challenges\
**Tags:** challenge:shell\
**Created:** [January 24, 2025, 12:53am UTC](https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430 "2025-01-24T00:53:29Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kristina-Pianykh](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/kristina-pianykh/32/4164_2.png) [@Kristina-Pianykh](https://forum.codecrafters.io/u/Kristina-Pianykh)\
**Post date:** [January 24, 2025, 12:53am UTC](https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430/1 "2025-01-24T00:53:29Z")

</div>

I’m stuck on Stage #GM9. I use Go for the challenge.

I just refactored my code to use the terminal raw mode to capture every keystroke on stdin. Upon ‘\r’ or ‘\n’ or on receiving the error `io.EOF`, I consider the input provided by the user as “entered” and restore the normal terminal mode. When I submit my program to move on to the next stage, the tests fail with the behavior I cannot reproduce when I run the same commands locally. Compare:

Local interactive mode

```auto
❯ ./your_program.sh
$ echo "world script"world script
world scriptworld script
$

```

Remote test output on submission

```auto
[your-program] $ echo "world script"world script
[tester::#TG6] Output does not match expected value.
[tester::#TG6] Expected: "$ echo "world script""
[tester::#TG6] Received: "$ echo "world script"world script"

```

Another example of test output:

```auto
[tester::#GP4] Running tests for Stage #GP4 (Navigation - The cd builtin: Home directory)
[tester::#GP4] Running ./your_program.sh
[your-program] $ cd /tmp/raspberry/orange/pear
[your-program] $ pwd
[your-program] /tmp/raspberry/orange/pear
[tester::#GP4] Received current working directory response
[your-program] $ cd ~
[your-program] $ pwd
[tester::#GP4] Output does not match expected value.
[tester::#GP4] Expected: "$ pwd"
[tester::#GP4] Received: "$ pwd/tmp/strawberry/mango/mango"
[your-program] $
[tester::#GP4] Assertion failed.
[tester::#GP4] Test failed

```

It appears as if the normal terminal mode is not restored.

The discrepancy in the behavior makes me think the test input is injected into the tested shell program. My question is: how? Is test input passed to my shell program by redirecting/piping it?

My input reading function:

```auto
func readInput(inputCh chan string) {
	var err error
	var oldState *term.State
	success := false

	oldState, err = term.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		panic(err)
	}

	buf := make([]byte, 1)
	input := []byte{}

	defer func() {
		input = append(input, '\n')
		if success {
			inputCh <- string(input)
		}
		fmt.Printf("\r\n")
		err := term.Restore(int(os.Stdin.Fd()), oldState)
		if err != nil {
			panic(err)
		}
		close(inputCh)
	}()

	for {
		_, err = os.Stdin.Read(buf)
		if err != nil {
			if errors.Is(err, io.EOF) {
				success = true
				return
			} else {
				panic(err)
			}
		}
		b := buf[0]

		switch b {
		case sigint:
			fmt.Printf("^C")
			return
		case cariageReturn, newLine:
			success = true
			return
		case tab:
			success = true
			if cmpl, ok := autocomplete(input); ok {
				clearPrompt()

				input = cmpl
				input = append(input, ' ')

				for i := range input {
					fmt.Printf("%c", input[i])
				}
			}
		case del:
			if len(input) > 0 {
				fmt.Print("\x1b[D \x1b[D")
				input = input[:len(input)-1]
			}
			continue
		default:
			fmt.Printf("%c", b)
			input = append(input, b)
		}
	}
}

```

Source code: [go-shell/cmd/myshell/main.go at master · Kristina-Pianykh/go-shell · GitHub](https://github.com/Kristina-Pianykh/go-shell/blob/master/cmd/myshell/main.go)

---

<div class="post-metadata">

**Author:** ![andy1li](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/andy1li/32/10_2.png) [@andy1li](https://forum.codecrafters.io/u/andy1li)\
**Post date:** [January 24, 2025, 12:57am UTC](https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430/2 "2025-01-24T00:57:47Z")

</div>

I’ll take a look and get back to you by the end of the week.

---

<div class="post-metadata">

**Author:** ![andy1li](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/andy1li/32/10_2.png) [@andy1li](https://forum.codecrafters.io/u/andy1li)\
**Post date:** [January 24, 2025, 5:34pm UTC](https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430/4 "2025-01-24T17:34:49Z")

</div>

Hi @Kristina-Pianykh I tried running your code locally, but it seems that it’s not handling `\n` or `\r` properly:

 ![image](https://canada1.discourse-cdn.com/flex003/uploads/codecrafters/original/2X/e/e4e233bf138a1519fc5d9f9e16b638a36f8ac98d.jpeg)

> My question is: how? Is test input passed to my shell program by redirecting/piping it?

To be honest, I’m not entirely sure about the details here. Just for context, our tester has been validated against several real-world shells, so it’s highly unlikely that the specific input method is causing issues.

Here’s the tester code in case you want to dig deeper:

> **[GitHub - codecrafters-io/shell-tester: Tester for the shell challenge.](https://github.com/codecrafters-io/shell-tester)**
>
> Tester for the shell challenge.

---

<div class="post-metadata">

**Author:** ![Kristina-Pianykh](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/kristina-pianykh/32/4164_2.png) [@Kristina-Pianykh](https://forum.codecrafters.io/u/Kristina-Pianykh)\
**Post date:** [January 25, 2025, 12:18am UTC](https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430/6 "2025-01-25T00:18:14Z")

</div>

Thank you so much for having a look, I really appreciate it! I’ll have a look at the testing repo a little later 🙂

What terminal/shell did you use to launch from though?  
I could reproduce the behavior on the native Linux console but not in Ghostty/kitty when launched from zsh or bash. After fixing a few things, the output on the native Linux console is as expected but the tests keep failing nonetheless (see the screenshot attached). I still cannot reproduce it locally.

 ![Screenshot From 2025-01-25 01-08-01](https://canada1.discourse-cdn.com/flex003/uploads/codecrafters/original/2X/d/d00369a7297ade3059be8bb750dd27a3e32cd5ff.png)

---

<div class="post-metadata">

**Author:** ![Kristina-Pianykh](https://yyz1.discourse-cdn.com/flex003/user_avatar/forum.codecrafters.io/kristina-pianykh/32/4164_2.png) [@Kristina-Pianykh](https://forum.codecrafters.io/u/Kristina-Pianykh)\
**Post date:** [January 25, 2025, 11:36pm UTC](https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430/8 "2025-01-25T23:36:09Z")

</div>

Solved it, the problem was super hard to catch and reproduce and had to do with racing gorutines. Sometimes the REPL would go into the next iteration on fast exit (typically on command not found) before the terminal is transferred back into normal mode in a separate goroutine. Thanks again for your time @andy1li !

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex003/uploads/codecrafters/original/3X/7/0/700657133935c15703e22c7c8870394f6e6dc27d.svg) [@system](https://forum.codecrafters.io/u/system)\
**Post date:** [January 30, 2025, 11:36pm UTC](https://forum.codecrafters.io/t/how-is-test-input-passed-to-shell-program-in-testing-environment/4430/9 "2025-01-30T23:36:21Z")

</div>

Closed on January 30, 2025, 11:36pm UTC

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.
