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
}