#JV5 Test Output different from the code itself

I’m stuck on Stage #JV5.

I’ve implemented the feature successfully and tested locally and everything works well. But the test fail based on an output that does not match. I have simulated the test locally and the out being reported by the test tool is not what is obtainable in manual testing.

Manual testing here:

go run app/*.go
$ cat output.txt nonexistent
README.md
app
codecrafters.yml
go.mod
go.sum
output.txt
test_dir
your_program.sh

cat: nonexistent: No such file or directory

Here are my logs:

remote: [tester::#JV1] Running tests for Stage #JV1 (Redirection - Redirect stdout)
remote: [tester::#JV1] [setup] export PATH=/tmp/apple/orange/mango:$PATH
remote: [tester::#JV1] Running ./your_program.sh
remote: [tester::#JV1] [setup] echo "apple" > "/tmp/pig/apple"
remote: [tester::#JV1] [setup] echo "blueberry" > "/tmp/pig/blueberry"
remote: [tester::#JV1] [setup] echo "grape" > "/tmp/pig/grape"
remote: [your-program] $ ls -1 /tmp/pig > /tmp/owl/cow.md
remote: [your-program] $ cat /tmp/owl/cow.md
remote: [your-program] apple
remote: [your-program] blueberry
remote: [your-program] grape
remote: [tester::#JV1] ✓ Received redirected file content
remote: [your-program] $ echo 'Hello David' 1> /tmp/owl/fox.md
remote: [your-program] $ cat /tmp/owl/fox.md
remote: [your-program] Hello David
remote: [tester::#JV1] ✓ Received redirected file content
remote: [your-program] $ cat /tmp/pig/blueberry nonexistent 1> /tmp/owl/owl.md
remote: [your-program] cat: can't open 'nonexistent': No such file or directory
remote: [tester::#JV1] ^ Line does not match expected value.
remote: [tester::#JV1] Expected: "cat: nonexistent: No such file or directory"
remote: [tester::#JV1] Received: "cat: can't open 'nonexistent': No such file or directory"
remote: [your-program] $
remote: [tester::#JV1] Assertion failed.
remote: [tester::#JV1] Test failed
remote:
remote: View our article on debugging test failures: https://codecrafters.io/debug

And here’s a snippet of my code:


func (c *Command) CustomCommand(cmd string, args []string) int {
	cmdPath := c.findExecutable(cmd)
	if cmdPath == "" {
		fmt.Printf("%s: command not found\n", c.tokens[0])
	}

	var outStream *os.File = os.Stdout // set the default output to standard output
	var execArgs []string = args       // set to already passed in args by default
	var err error
	shouldClose := false

	// it means there is a redirection to STDOUT
	if slices.Contains(args, ">") || slices.Contains(args, "1>") {
		outStream, execArgs, err = c.createCustomStdout(args)
		shouldClose = true
	}

	if err != nil {
		fmt.Fprintf(os.Stderr, "%s: %s: No such file or directory\n", cmd, strings.Join(execArgs, " "))
		return 1
	}

	if shouldClose {
		defer outStream.Close()
	}
	command := exec.Command(cmdPath, execArgs...)
	command.Args = append([]string{cmd}, execArgs...)

	command.Stdout = outStream
	command.Stdin = os.Stdin
	command.Stderr = os.Stderr

	if err := command.Run(); err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			return exitError.ExitCode()
		}
		return 1
	}

	return 0
}

func (c *Command) createCustomStdout(args []string) (*os.File, []string, error) {
	var execArgs []string
	var filePath []string

	for i, arg := range args {
		if arg == ">" || arg == "1>" {
			filePath = append(filePath, args[i+1:]...)
			break
		}

		execArgs = append(execArgs, arg)
	}

	file, err := os.Create(strings.Join(filePath, ""))
	if err != nil {
		return nil, nil, err
	}

	return file, execArgs, nil
}

Hey @Varsilias, could you upload your code to GitHub and share the link? It will be much easier to debug if I can run it directly.

Thank you.

Here it is

Here’s a strange place you could try to look. There once was a similar looking problem where output command varied because the program ended up finding a different version of, think it was ls than where the test runner was looking. I noticed your findExecutable uses a function WalkDir. I don’t use Go but the docs suggest they walk the entire tree, so you might end up finding a different cat command. Suppose was path was [/a, /b] . We might not have /a/cat but end up finding it at /a/c/cat.

1 Like

Thank you very much.

This solved the issue.

I had to rewrite the findExecutable function. Also added an optimization

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