Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readLine() CR/LF issue #28

Open
smileart opened this issue Jan 4, 2017 · 1 comment
Open

readLine() CR/LF issue #28

smileart opened this issue Jan 4, 2017 · 1 comment

Comments

@smileart
Copy link

smileart commented Jan 4, 2017

Hey there! 👋

I tried to use gexpect to test a CLI app and encountered an issue regarding expected and actual line endings (i.e. 0xa/0xd). On echo 'test\n' I was expecting to get test\n, but unfortunately I get test\r as a return value of the readLine function. If my target app outputs multiline go string with \n as a line separator, I simply can't use the same string as a test expectation since the concatenated result of the reading of all the lines will be separated with \rs.

Here is a minimal code sample to reproduce:

package main

import (
	"fmt"

	"github.com/ThomasRooney/gexpect"
)

func main() {
	child, err := gexpect.Spawn("echo 'test\n'")
	if err != nil {
		panic(err)
	}

	expected := "test\n"

	actual, _ := child.ReadLine()
	fmt.Println("Expected:")
	fmt.Printf("%#v", expected)
	fmt.Println()
	fmt.Printf("%#v", []byte(expected))
	fmt.Println("\n=========================")
	fmt.Println("Actual:")
	fmt.Printf("%#v", actual)
	fmt.Println()
	fmt.Printf("%#v", []byte(actual))
}

On my machine (MacOS Sierra 10.12.2, zsh 5.3, go 1.7.4 darwin/amd64) it results in:

Expected:
"test\n"
[]byte{0x74, 0x65, 0x73, 0x74, 0xa}
=========================
Actual:
"test\r"
[]byte{0x74, 0x65, 0x73, 0x74, 0xd}

If I change the test string in above code to test\r the result will be:

Expected:
"test\r"
[]byte{0x74, 0x65, 0x73, 0x74, 0xd}
=========================
Actual:
"test\r\r"
[]byte{0x74, 0x65, 0x73, 0x74, 0xd, 0xd}
@smileart
Copy link
Author

smileart commented Mar 2, 2017

Got some time to investigate this issue and discovered that in my terminal (MacOS Sierra 10.12.3, iTerm 2, Build 3.0.14 with zsh 5.3) I have such a behaviour:

gexpect.Spawn("echo 'test'")        # => []byte{0x74, 0x65, 0x73, 0x74, 0xd, 0xa}
gexpect.Spawn("echo 'test\n'")      # => []byte{0x74, 0x65, 0x73, 0x74, 0xd, 0xa, 0xd, 0xa}
gexpect.Spawn("echo 'test\r'")      # => []byte{0x74, 0x65, 0x73, 0x74, 0xd, 0xd, 0xa}
gexpect.Spawn("echo 'test\r\n'")    # => []byte{0x74, 0x65, 0x73, 0x74, 0xd, 0xd, 0xa, 0xd, 0xa} 

So since any \n produces actual \r\n ReadUntil looks for one byte only and in a situation when I "echo 'test\n'" it matches the first char '\r' in a pair \r\n and leaves \n. Than's how I got this case:

Expected:
"test\n"
[]byte{0x74, 0x65, 0x73, 0x74, 0xa}
=========================
Actual:
"test\r"
[]byte{0x74, 0x65, 0x73, 0x74, 0xd}

In the second one I spawn "echo 'test\r' which produces actual \r\r\n:

Expected:
"test\r"
[]byte{0x74, 0x65, 0x73, 0x74, 0xd}
=========================
Actual:
"test\r\r"
[]byte{0x74, 0x65, 0x73, 0x74, 0xd, 0xd}

So I suppose without changing ReadUntil's signature from one byte argument as a delimiter to an array of strings we couldn't actually match different CRs for different systems. Therefore I quickly patched it a little bit in my fork here: smileart@d09013d and it seems to work well.

Would be great to hear from you. Would you recon accepting it as a pull request? What about backward compatibility for ReadUntil function? Should I refactor those nested IFs and FORs into separate helper functions? Etc. Cheers! ✌️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant