From cd13abdf5059685bd70d53687f842e27c1142ff3 Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Fri, 11 May 2018 12:34:33 -0500 Subject: [PATCH] Config tests --- control/cmd_conf.go | 4 +- control/cmd_misc.go | 2 +- control/controltest/cmd_authenticate_test.go | 12 ++++ control/controltest/cmd_conf_test.go | 72 ++++++++++++++++++++ control/controltest/test_context.go | 10 +++ control/controltest/test_tor.go | 8 ++- control/response.go | 7 +- process/creator.go | 6 +- 8 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 control/controltest/cmd_conf_test.go diff --git a/control/cmd_conf.go b/control/cmd_conf.go index 4096593..39cda49 100644 --- a/control/cmd_conf.go +++ b/control/cmd_conf.go @@ -15,11 +15,11 @@ func NewConfEntry(key string, value *string) *ConfEntry { return &ConfEntry{Key: key, Value: value} } -func (c *Conn) SetConf(entries []*ConfEntry) error { +func (c *Conn) SetConf(entries ...*ConfEntry) error { return c.sendSetConf("SETCONF", entries) } -func (c *Conn) ResetConf(entries []*ConfEntry) error { +func (c *Conn) ResetConf(entries ...*ConfEntry) error { return c.sendSetConf("RESETCONF", entries) } diff --git a/control/cmd_misc.go b/control/cmd_misc.go index aa852d3..64a0bf2 100644 --- a/control/cmd_misc.go +++ b/control/cmd_misc.go @@ -48,7 +48,7 @@ type InfoValue struct { } func (c *Conn) GetInfo(keys ...string) ([]*InfoValue, error) { - resp, err := c.SendRequest("GETCONF %v", strings.Join(keys, " ")) + resp, err := c.SendRequest("GETINFO %v", strings.Join(keys, " ")) if err != nil { return nil, err } diff --git a/control/controltest/cmd_authenticate_test.go b/control/controltest/cmd_authenticate_test.go index b8233a8..b962edc 100644 --- a/control/controltest/cmd_authenticate_test.go +++ b/control/controltest/cmd_authenticate_test.go @@ -5,12 +5,20 @@ import "testing" func TestAuthenticateNull(t *testing.T) { ctx, conn := NewTestContextConnected(t) defer ctx.CloseConnected(conn) + // Verify auth methods before auth + info, err := conn.ProtocolInfo() + ctx.Require.NoError(err) + ctx.Require.ElementsMatch([]string{"NULL"}, info.AuthMethods) ctx.Require.NoError(conn.Authenticate("")) } func TestAuthenticateSafeCookie(t *testing.T) { ctx, conn := NewTestContextConnected(t, "--CookieAuthentication", "1") defer ctx.CloseConnected(conn) + // Verify auth methods before auth + info, err := conn.ProtocolInfo() + ctx.Require.NoError(err) + ctx.Require.ElementsMatch([]string{"COOKIE", "SAFECOOKIE"}, info.AuthMethods) ctx.Require.NoError(conn.Authenticate("")) } @@ -19,5 +27,9 @@ func TestAuthenticateHashedPassword(t *testing.T) { ctx, conn := NewTestContextConnected(t, "--HashedControlPassword", "16:5417AE717521511A609921392778FFA8518EC089BF2162A199241AEB4A") defer ctx.CloseConnected(conn) + // Verify auth methods before auth + info, err := conn.ProtocolInfo() + ctx.Require.NoError(err) + ctx.Require.ElementsMatch([]string{"HASHESPASSWORD"}, info.AuthMethods) ctx.Require.NoError(conn.Authenticate("testpass")) } diff --git a/control/controltest/cmd_conf_test.go b/control/controltest/cmd_conf_test.go new file mode 100644 index 0000000..619d5d4 --- /dev/null +++ b/control/controltest/cmd_conf_test.go @@ -0,0 +1,72 @@ +package controltest + +import ( + "io/ioutil" + "testing" + + "github.com/cretz/bine/control" +) + +func TestGetSetAndResetConf(t *testing.T) { + ctx, conn := NewTestContextAuthenticated(t) + defer ctx.CloseConnected(conn) + // Simple get conf + assertConfVals := func(val string) { + entries, err := conn.GetConf("LogMessageDomains", "ProtocolWarnings") + ctx.Require.NoError(err) + ctx.Require.Len(entries, 2) + ctx.Require.Contains(entries, &control.ConfEntry{Key: "LogMessageDomains", Value: &val}) + ctx.Require.Contains(entries, &control.ConfEntry{Key: "ProtocolWarnings", Value: &val}) + } + assertConfVals("0") + // Change em both to 1 + one := "1" + err := conn.SetConf(&control.ConfEntry{Key: "LogMessageDomains", Value: &one}, + &control.ConfEntry{Key: "ProtocolWarnings", Value: &one}) + ctx.Require.NoError(err) + // Check again + assertConfVals(one) + // Reset em both + err = conn.ResetConf(&control.ConfEntry{Key: "LogMessageDomains"}, &control.ConfEntry{Key: "ProtocolWarnings"}) + ctx.Require.NoError(err) + // Make sure both back to zero + assertConfVals("0") +} + +func TestLoadConf(t *testing.T) { + ctx, conn := NewTestContextAuthenticated(t) + defer ctx.CloseConnected(conn) + // Get entire conf text + vals, err := conn.GetInfo("config-text") + ctx.Require.NoError(err) + ctx.Require.Len(vals, 1) + ctx.Require.Equal("config-text", vals[0].Key) + confText := vals[0].Value + // Append new conf val and load + ctx.Require.NotContains(confText, "LogMessageDomains") + confText += "\r\nLogMessageDomains 1" + ctx.Require.NoError(conn.LoadConf(confText)) + // Check the new val + vals, err = conn.GetInfo("config-text") + ctx.Require.NoError(err) + ctx.Require.Len(vals, 1) + ctx.Require.Equal("config-text", vals[0].Key) + ctx.Require.Contains(vals[0].Value, "LogMessageDomains 1") +} + +func TestSaveConf(t *testing.T) { + ctx, conn := NewTestContextAuthenticated(t) + defer ctx.CloseConnected(conn) + // Get conf filename + vals, err := conn.GetInfo("config-file") + ctx.Require.NoError(err) + ctx.Require.Len(vals, 1) + ctx.Require.Equal("config-file", vals[0].Key) + confFile := vals[0].Value + // Save it + ctx.Require.NoError(conn.SaveConf(false)) + // Read and make sure, say, the DataDirectory is accurate + confText, err := ioutil.ReadFile(confFile) + ctx.Require.NoError(err) + ctx.Require.Contains(string(confText), "DataDirectory "+ctx.TestTor.DataDir) +} diff --git a/control/controltest/test_context.go b/control/controltest/test_context.go index c124502..0de6b83 100644 --- a/control/controltest/test_context.go +++ b/control/controltest/test_context.go @@ -35,6 +35,16 @@ func NewTestContextConnected(t *testing.T, extraTorArgs ...string) (*TestContext return ctx, conn } +func NewTestContextAuthenticated(t *testing.T, extraTorArgs ...string) (*TestContext, *control.Conn) { + ctx, conn := NewTestContextConnected(t, extraTorArgs...) + if err := conn.Authenticate(""); err != nil { + conn.Close() + ctx.Close() + ctx.Fatal(err) + } + return ctx, conn +} + func (t *TestContext) EnsureTestTorStarted() { if t.TestTor == nil { var err error diff --git a/control/controltest/test_tor.go b/control/controltest/test_tor.go index 7694d69..78c3c1f 100644 --- a/control/controltest/test_tor.go +++ b/control/controltest/test_tor.go @@ -15,7 +15,7 @@ import ( var torExePath string func init() { - flag.StringVar(&torExePath, "tor", "tor", "The TOR exe path") + flag.StringVar(&torExePath, "tor.path", "tor", "The TOR exe path") flag.Parse() } @@ -33,9 +33,15 @@ func StartTestTor(ctx context.Context, extraArgs ...string) (*TestTor, error) { return nil, err } controlPortFile := filepath.Join(dataDir, "control-port") + // We have to touch the torrc + torrcFile := filepath.Join(dataDir, "test-torrc") + if err = ioutil.WriteFile(torrcFile, nil, os.FileMode(0600)); err != nil { + return nil, err + } ret := &TestTor{ DataDir: dataDir, OrigArgs: append([]string{ + "-f", torrcFile, // "--quiet", "--DisableNetwork", "1", "--ControlPort", "auto", diff --git a/control/response.go b/control/response.go index dc3bef3..cdf371c 100644 --- a/control/response.go +++ b/control/response.go @@ -82,13 +82,14 @@ func (c *Conn) ReadResponse() (*Response, error) { resp.Data = append(resp.Data, line[4:]) case '+': // A "dot-encoded" payload follows. - resp.Data = append(resp.Data, line[4:]) dotBody, err := c.conn.ReadDotBytes() if err != nil { return nil, err } - resp.Data = append(resp.Data, strings.TrimRight(string(dotBody), "\n\r")) - dotLines := strings.Split(string(dotBody), "\n") + dotBodyStr := strings.TrimRight(string(dotBody), "\n\r") + c.debugf("Read dot body:\n---\n%v\n---", dotBodyStr) + resp.Data = append(resp.Data, line[4:]+dotBodyStr) + dotLines := strings.Split(dotBodyStr, "\n") for _, dotLine := range dotLines[:len(dotLines)-1] { resp.RawLines = append(resp.RawLines, dotLine) } diff --git a/process/creator.go b/process/creator.go index e122fcb..17ad99a 100644 --- a/process/creator.go +++ b/process/creator.go @@ -2,6 +2,7 @@ package process import ( "context" + "os" "os/exec" ) @@ -17,5 +18,8 @@ func NewProcessCreator(exePath string) ProcessCreator { return &exeProcessCreator{exePath} } func (e *exeProcessCreator) New(ctx context.Context, args ...string) (Process, error) { - return &exeProcess{Cmd: exec.CommandContext(ctx, e.exePath, args...)}, nil + proc := &exeProcess{Cmd: exec.CommandContext(ctx, e.exePath, args...)} + proc.Stdout = os.Stdout + proc.Stderr = os.Stderr + return proc, nil }