diff options
| author | Shulhan <ms@kilabit.info> | 2023-10-12 01:34:59 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2023-10-12 22:14:51 +0700 |
| commit | a0c9e5e87e951df4d1bc86c6ccc2ed73dbe7f942 (patch) | |
| tree | d0650c477fff66fe87afb51233ce9c88e8c9fd79 | |
| parent | 207e7f016bf96ab037f510837940c037111cd42f (diff) | |
| download | awwan-a0c9e5e87e951df4d1bc86c6ccc2ed73dbe7f942.tar.xz | |
all: add integration tests for magic command "#get!"
| -rw-r--r-- | awwan_sudo_test.go | 100 | ||||
| -rw-r--r-- | request.go | 13 | ||||
| -rw-r--r-- | session.go | 22 | ||||
| -rw-r--r-- | testdata/local/get.aww | 2 | ||||
| -rw-r--r-- | testdata/local/get.data | 15 |
5 files changed, 142 insertions, 10 deletions
diff --git a/awwan_sudo_test.go b/awwan_sudo_test.go new file mode 100644 index 0000000..720726c --- /dev/null +++ b/awwan_sudo_test.go @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2023 M. Shulhan <ms@kilabit.info> +// SPDX-License-Identifier: GPL-3.0-or-later + +//go:build integration + +package awwan + +import ( + "bytes" + "os" + "path/filepath" + "testing" + + "github.com/shuLhan/share/lib/test" + "github.com/shuLhan/share/lib/test/mock" +) + +func TestAwwan_Local_SudoGet(t *testing.T) { + type testCase struct { + desc string + lineRange string + fileDest string + sudoPass string + expContent string + expError string + } + + // Load the test data. + var ( + baseDir = filepath.Join(`testdata`, `local`) + testdataFile = filepath.Join(baseDir, `get.data`) + + tdata *test.Data + err error + ) + + tdata, err = test.LoadData(testdataFile) + if err != nil { + t.Fatal(err) + } + + var ( + mockrw = mock.ReadWriter{} + + aww *Awwan + ) + + aww, err = New(baseDir) + if err != nil { + t.Fatal(err) + } + + // Mock terminal to read passphrase for private key. + aww.cryptoc.termrw = &mockrw + + var cases = []testCase{{ + desc: `WithPlainFile`, + lineRange: `3`, + sudoPass: "awwan\r\n", + fileDest: filepath.Join(baseDir, `tmp`, `os-release`), + expContent: string(tdata.Output[`tmp/os-release`]), + }, { + desc: `WithInvalidPassword`, + lineRange: `3`, + sudoPass: "invalid\r\n", + expError: `Local: SudoCopy: ExecLocal: exit status 1`, + }} + + var ( + script = filepath.Join(baseDir, `get.aww`) + mockStdin = bytes.Buffer{} + + c testCase + gotContent []byte + ) + + for _, c = range cases { + t.Log(c.desc) + + var req = NewRequest(CommandModeLocal, script, c.lineRange) + + // Mock the request stdin to read password from buffer. + mockStdin.Reset() + mockStdin.WriteString(c.sudoPass) + req.stdin = &mockStdin + + err = aww.Local(req) + if err != nil { + test.Assert(t, `Local: error`, c.expError, err.Error()) + continue + } + + gotContent, err = os.ReadFile(c.fileDest) + if err != nil { + t.Fatal(err) + } + + test.Assert(t, `content`, c.expContent, string(gotContent)) + } +} @@ -12,11 +12,14 @@ import ( // Each request define the Mode of execution, Script file to be executed, // and the lineRange -- list of line numbers to be executed. type Request struct { - // Each request may set the Writer where the command output and - // error will be written. - // If its nil, it will default to os.Stdout and os.Stderr. - stdout io.Writer - stderr io.Writer + // Each request may set the Writer where the command read input from + // or output and error will be written. + // If its nil, it will default to os.DevNull (default os + // [exec/Cmd]), os.Stdout, and os.Stderr, respectively. + stdin io.Reader + stdout io.Writer + stderr io.Writer + scriptPath string // The actual or cleaned up path of the Script. script *Script @@ -214,9 +214,16 @@ func (ses *Session) SudoCopy(req *Request, stmt *Statement) (err error) { sudoCp = &Statement{ kind: statementKindDefault, - cmd: "sudo", - args: []string{"cp", src, dst}, - raw: []byte(`sudo cp "` + src + `" "` + dst + `"`), + } + + // Detect which stdin we use. + // If its non-nil, use "sudo -S" to read password from stdin instead + // of from terminal. + // This will allow us to test sudo behaviour. + if req.stdin == nil { + sudoCp.raw = []byte(`sudo cp "` + src + `" "` + dst + `"`) + } else { + sudoCp.raw = []byte(`sudo -S cp "` + src + `" "` + dst + `"`) } err = ses.ExecLocal(req, sudoCp) @@ -280,9 +287,16 @@ func (ses *Session) ExecLocal(req *Request, stmt *Statement) (err error) { args = string(stmt.raw) cmd = exec.Command(`/bin/sh`, `-c`, args) ) + + cmd.Stdin = req.stdin cmd.Stdout = req.stdout cmd.Stderr = req.stderr - return cmd.Run() + + err = cmd.Run() + if err != nil { + return fmt.Errorf(`ExecLocal: %w`, err) + } + return nil } // executeRequires run the "#require:" statements from line 0 until diff --git a/testdata/local/get.aww b/testdata/local/get.aww index 15878c6..d889f22 100644 --- a/testdata/local/get.aww +++ b/testdata/local/get.aww @@ -1 +1,3 @@ #get: {{.ScriptDir}}/plain.txt {{.ScriptDir}}/tmp/get_plain.txt + +#get! /etc/os-release {{.ScriptDir}}/tmp/os-release diff --git a/testdata/local/get.data b/testdata/local/get.data index 0e7ee57..c0e24ec 100644 --- a/testdata/local/get.data +++ b/testdata/local/get.data @@ -1,5 +1,18 @@ -Test on magic command "#get:". +Test output from magic command "#get:" and "#get!" <<< tmp/get_plain.txt The host name is {{.Val "host::name"}}. + +<<< tmp/os-release +NAME="Arch Linux" +PRETTY_NAME="Arch Linux" +ID=arch +BUILD_ID=rolling +ANSI_COLOR="38;2;23;147;209" +HOME_URL="https://archlinux.org/" +DOCUMENTATION_URL="https://wiki.archlinux.org/" +SUPPORT_URL="https://bbs.archlinux.org/" +BUG_REPORT_URL="https://bugs.archlinux.org/" +PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/" +LOGO=archlinux-logo |
