mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-17 12:31:06 +01:00
Changed print funcs to use an io.Writer, reimplemented print tests
This commit is contained in:
@@ -89,7 +89,7 @@ func PrepareColumns(data *Tabdata) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prepare headers: add numbers to headers
|
// prepare headers: add numbers to headers
|
||||||
func numberizeHeaders(data *Tabdata) {
|
func numberizeAndReduceHeaders(data *Tabdata) {
|
||||||
numberedHeaders := []string{}
|
numberedHeaders := []string{}
|
||||||
maxwidth := 0 // start from scratch, so we only look at displayed column widths
|
maxwidth := 0 // start from scratch, so we only look at displayed column widths
|
||||||
|
|
||||||
|
|||||||
@@ -158,9 +158,9 @@ func TestNumberizeHeaders(t *testing.T) {
|
|||||||
UseColumns = tt.columns
|
UseColumns = tt.columns
|
||||||
NoNumbering = tt.nonum
|
NoNumbering = tt.nonum
|
||||||
usedata := data
|
usedata := data
|
||||||
numberizeHeaders(&usedata)
|
numberizeAndReduceHeaders(&usedata)
|
||||||
if !reflect.DeepEqual(usedata.headers, tt.expect) {
|
if !reflect.DeepEqual(usedata.headers, tt.expect) {
|
||||||
t.Errorf("numberizeHeaders returned invalid data:\ngot: %+v\nexp: %+v",
|
t.Errorf("numberizeAndReduceHeaders returned invalid data:\ngot: %+v\nexp: %+v",
|
||||||
usedata.headers, tt.expect)
|
usedata.headers, tt.expect)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func ProcessFiles(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
printData(&data)
|
printData(os.Stdout, &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -22,20 +22,18 @@ import (
|
|||||||
"github.com/gookit/color"
|
"github.com/gookit/color"
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printData(data *Tabdata) {
|
func printData(w io.Writer, data *Tabdata) string {
|
||||||
// some output preparations:
|
// some output preparations:
|
||||||
|
|
||||||
if OutputMode != "shell" {
|
// add numbers to headers and remove this we're not interested in
|
||||||
// not needed in eval string
|
numberizeAndReduceHeaders(data)
|
||||||
numberizeHeaders(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove unwanted columns, if any
|
// remove unwanted columns, if any
|
||||||
reduceColumns(data)
|
reduceColumns(data)
|
||||||
@@ -45,26 +43,31 @@ func printData(data *Tabdata) {
|
|||||||
|
|
||||||
switch OutputMode {
|
switch OutputMode {
|
||||||
case "extended":
|
case "extended":
|
||||||
printExtendedData(data)
|
return printExtendedData(w, data)
|
||||||
case "ascii":
|
case "ascii":
|
||||||
printAsciiData(data)
|
return printAsciiData(w, data)
|
||||||
case "orgtbl":
|
case "orgtbl":
|
||||||
printOrgmodeData(data)
|
return printOrgmodeData(w, data)
|
||||||
case "markdown":
|
case "markdown":
|
||||||
printMarkdownData(data)
|
return printMarkdownData(w, data)
|
||||||
case "shell":
|
case "shell":
|
||||||
printShellData(data)
|
return printShellData(w, data)
|
||||||
case "yaml":
|
case "yaml":
|
||||||
printYamlData(data)
|
return printYamlData(w, data)
|
||||||
default:
|
default:
|
||||||
printAsciiData(data)
|
return printAsciiData(w, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func output(w io.Writer, str string) string {
|
||||||
|
fmt.Fprint(w, str)
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Emacs org-mode compatible table (also orgtbl-mode)
|
Emacs org-mode compatible table (also orgtbl-mode)
|
||||||
*/
|
*/
|
||||||
func printOrgmodeData(data *Tabdata) {
|
func printOrgmodeData(w io.Writer, data *Tabdata) string {
|
||||||
tableString := &strings.Builder{}
|
tableString := &strings.Builder{}
|
||||||
table := tablewriter.NewWriter(tableString)
|
table := tablewriter.NewWriter(tableString)
|
||||||
|
|
||||||
@@ -90,16 +93,16 @@ func printOrgmodeData(data *Tabdata) {
|
|||||||
leftR := regexp.MustCompile("(?m)^\\+")
|
leftR := regexp.MustCompile("(?m)^\\+")
|
||||||
rightR := regexp.MustCompile("\\+(?m)$")
|
rightR := regexp.MustCompile("\\+(?m)$")
|
||||||
|
|
||||||
color.Print(
|
return output(w, color.Sprint(
|
||||||
colorizeData(
|
colorizeData(
|
||||||
rightR.ReplaceAllString(
|
rightR.ReplaceAllString(
|
||||||
leftR.ReplaceAllString(tableString.String(), "|"), "|")))
|
leftR.ReplaceAllString(tableString.String(), "|"), "|"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Markdown table
|
Markdown table
|
||||||
*/
|
*/
|
||||||
func printMarkdownData(data *Tabdata) {
|
func printMarkdownData(w io.Writer, data *Tabdata) string {
|
||||||
tableString := &strings.Builder{}
|
tableString := &strings.Builder{}
|
||||||
table := tablewriter.NewWriter(tableString)
|
table := tablewriter.NewWriter(tableString)
|
||||||
|
|
||||||
@@ -113,13 +116,13 @@ func printMarkdownData(data *Tabdata) {
|
|||||||
table.SetCenterSeparator("|")
|
table.SetCenterSeparator("|")
|
||||||
|
|
||||||
table.Render()
|
table.Render()
|
||||||
color.Print(colorizeData(tableString.String()))
|
return output(w, color.Sprint(colorizeData(tableString.String())))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Simple ASCII table without any borders etc, just like the input we expect
|
Simple ASCII table without any borders etc, just like the input we expect
|
||||||
*/
|
*/
|
||||||
func printAsciiData(data *Tabdata) {
|
func printAsciiData(w io.Writer, data *Tabdata) string {
|
||||||
tableString := &strings.Builder{}
|
tableString := &strings.Builder{}
|
||||||
table := tablewriter.NewWriter(tableString)
|
table := tablewriter.NewWriter(tableString)
|
||||||
|
|
||||||
@@ -143,53 +146,48 @@ func printAsciiData(data *Tabdata) {
|
|||||||
table.SetNoWhiteSpace(true)
|
table.SetNoWhiteSpace(true)
|
||||||
|
|
||||||
table.Render()
|
table.Render()
|
||||||
color.Print(colorizeData(tableString.String()))
|
return output(w, color.Sprint(colorizeData(tableString.String())))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We simulate the \x command of psql (the PostgreSQL client)
|
We simulate the \x command of psql (the PostgreSQL client)
|
||||||
*/
|
*/
|
||||||
func printExtendedData(data *Tabdata) {
|
func printExtendedData(w io.Writer, data *Tabdata) string {
|
||||||
// needed for data output
|
// needed for data output
|
||||||
format := fmt.Sprintf("%%%ds: %%s\n", data.maxwidthHeader)
|
format := fmt.Sprintf("%%%ds: %%s\n", data.maxwidthHeader)
|
||||||
|
out := ""
|
||||||
if len(data.entries) > 0 {
|
if len(data.entries) > 0 {
|
||||||
for _, entry := range data.entries {
|
for _, entry := range data.entries {
|
||||||
for i, value := range entry {
|
for i, value := range entry {
|
||||||
color.Printf(format, data.headers[i], value)
|
out += color.Sprintf(format, data.headers[i], value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println()
|
out += "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return output(w, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Shell output, ready to be eval'd. Just like FreeBSD stat(1)
|
Shell output, ready to be eval'd. Just like FreeBSD stat(1)
|
||||||
*/
|
*/
|
||||||
func printShellData(data *Tabdata) {
|
func printShellData(w io.Writer, data *Tabdata) string {
|
||||||
|
out := ""
|
||||||
if len(data.entries) > 0 {
|
if len(data.entries) > 0 {
|
||||||
var idx int
|
|
||||||
for _, entry := range data.entries {
|
for _, entry := range data.entries {
|
||||||
idx = 0
|
|
||||||
shentries := []string{}
|
shentries := []string{}
|
||||||
for i, value := range entry {
|
for i, value := range entry {
|
||||||
if len(Columns) > 0 {
|
|
||||||
if !contains(UseColumns, i+1) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shentries = append(shentries, fmt.Sprintf("%s=\"%s\"",
|
shentries = append(shentries, fmt.Sprintf("%s=\"%s\"",
|
||||||
data.headers[idx], value))
|
data.headers[i], value))
|
||||||
idx++
|
|
||||||
}
|
}
|
||||||
fmt.Println(strings.Join(shentries, " "))
|
out += fmt.Sprint(strings.Join(shentries, " ")) + "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return output(w, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printYamlData(data *Tabdata) {
|
func printYamlData(w io.Writer, data *Tabdata) string {
|
||||||
type D struct {
|
type D struct {
|
||||||
Entries []map[string]interface{} `yaml:"entries"`
|
Entries []map[string]interface{} `yaml:"entries"`
|
||||||
}
|
}
|
||||||
@@ -222,5 +220,5 @@ func printYamlData(data *Tabdata) {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Stdout.Write(yamlstr)
|
return output(w, string(yamlstr))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,232 +18,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gookit/color"
|
//"github.com/alecthomas/repr"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func stdout2pipe(t *testing.T) (*os.File, *os.File) {
|
var mockdata = Tabdata{
|
||||||
reader, writer, err := os.Pipe()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
origStdout := os.Stdout
|
|
||||||
os.Stdout = writer
|
|
||||||
|
|
||||||
// we need to tell the color mode the io.Writer, even if we don't usw colorization
|
|
||||||
color.SetOutput(writer)
|
|
||||||
|
|
||||||
return origStdout, reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrinter(t *testing.T) {
|
|
||||||
startdata := Tabdata{
|
|
||||||
maxwidthHeader: 5,
|
|
||||||
maxwidthPerCol: []int{
|
|
||||||
5,
|
|
||||||
5,
|
|
||||||
8,
|
|
||||||
},
|
|
||||||
columns: 3,
|
|
||||||
headers: []string{
|
|
||||||
"ONE", "TWO", "THREE",
|
|
||||||
},
|
|
||||||
entries: [][]string{
|
|
||||||
{
|
|
||||||
"asd", "igig", "cxxxncnc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"19191", "EDD 1", "X",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
expects := map[string]string{
|
|
||||||
"ascii": `ONE(1) TWO(2) THREE(3)
|
|
||||||
asd igig cxxxncnc
|
|
||||||
19191 EDD 1 X`,
|
|
||||||
|
|
||||||
"orgtbl": `|--------+--------+----------|
|
|
||||||
| ONE(1) | TWO(2) | THREE(3) |
|
|
||||||
|--------+--------+----------|
|
|
||||||
| asd | igig | cxxxncnc |
|
|
||||||
| 19191 | EDD 1 | X |
|
|
||||||
|--------+--------+----------|`,
|
|
||||||
|
|
||||||
"markdown": `| ONE(1) | TWO(2) | THREE(3) |
|
|
||||||
|--------|--------|----------|
|
|
||||||
| asd | igig | cxxxncnc |
|
|
||||||
| 19191 | EDD 1 | X |`,
|
|
||||||
|
|
||||||
"shell": `ONE="asd" TWO="igig" THREE="cxxxncnc"
|
|
||||||
ONE="19191" TWO="EDD 1" THREE="X"`,
|
|
||||||
|
|
||||||
"extended": `ONE(1): asd
|
|
||||||
TWO(2): igig
|
|
||||||
THREE(3): cxxxncnc
|
|
||||||
|
|
||||||
ONE(1): 19191
|
|
||||||
TWO(2): EDD 1
|
|
||||||
THREE(3): X`,
|
|
||||||
"yaml": `entries:
|
|
||||||
- one: "asd"
|
|
||||||
three: "cxxxncnc"
|
|
||||||
two: "igig"
|
|
||||||
- one: 19191
|
|
||||||
three: "X"
|
|
||||||
two: "EDD 1"`,
|
|
||||||
}
|
|
||||||
|
|
||||||
NoColor = true
|
|
||||||
SortByColumn = 0 // disable sorting
|
|
||||||
|
|
||||||
origStdout, reader := stdout2pipe(t)
|
|
||||||
|
|
||||||
for mode, expect := range expects {
|
|
||||||
testname := fmt.Sprintf("print-%s", mode)
|
|
||||||
t.Run(testname, func(t *testing.T) {
|
|
||||||
|
|
||||||
OutputMode = mode
|
|
||||||
|
|
||||||
if mode == "yaml" {
|
|
||||||
NoNumbering = true
|
|
||||||
} else {
|
|
||||||
NoNumbering = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to reset our mock data, since it's being
|
|
||||||
// modified in printData()
|
|
||||||
data := startdata
|
|
||||||
printData(&data)
|
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
|
||||||
n, err := reader.Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
buf = buf[:n]
|
|
||||||
output := strings.TrimSpace(string(buf))
|
|
||||||
|
|
||||||
if output != expect {
|
|
||||||
t.Errorf("output mode: %s, got:\n%s\nwant:\n%s\n (%d <=> %d)",
|
|
||||||
mode, output, expect, len(output), len(expect))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore
|
|
||||||
os.Stdout = origStdout
|
|
||||||
NoNumbering = false
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSortPrinter(t *testing.T) {
|
|
||||||
startdata := Tabdata{
|
|
||||||
maxwidthHeader: 5,
|
|
||||||
maxwidthPerCol: []int{
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
2,
|
|
||||||
},
|
|
||||||
columns: 3,
|
|
||||||
headers: []string{
|
|
||||||
"ONE", "TWO", "THREE",
|
|
||||||
},
|
|
||||||
entries: [][]string{
|
|
||||||
{
|
|
||||||
"abc", "345", "b1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bcd", "234", "a2",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cde", "123", "c3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var tests = []struct {
|
|
||||||
data Tabdata
|
|
||||||
sortby int
|
|
||||||
desc bool
|
|
||||||
expect string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
data: startdata,
|
|
||||||
sortby: 1,
|
|
||||||
desc: false,
|
|
||||||
expect: `ONE(1) TWO(2) THREE(3)
|
|
||||||
abc 345 b1
|
|
||||||
bcd 234 a2
|
|
||||||
cde 123 c3`,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
data: startdata,
|
|
||||||
sortby: 2,
|
|
||||||
desc: false,
|
|
||||||
expect: `ONE(1) TWO(2) THREE(3)
|
|
||||||
cde 123 c3
|
|
||||||
bcd 234 a2
|
|
||||||
abc 345 b1`,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
data: startdata,
|
|
||||||
sortby: 3,
|
|
||||||
desc: false,
|
|
||||||
expect: `ONE(1) TWO(2) THREE(3)
|
|
||||||
bcd 234 a2
|
|
||||||
abc 345 b1
|
|
||||||
cde 123 c3`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: startdata,
|
|
||||||
sortby: 1,
|
|
||||||
desc: true,
|
|
||||||
expect: `ONE(1) TWO(2) THREE(3)
|
|
||||||
cde 123 c3
|
|
||||||
bcd 234 a2
|
|
||||||
abc 345 b1`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
NoColor = true
|
|
||||||
OutputMode = "ascii"
|
|
||||||
origStdout, reader := stdout2pipe(t)
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
testname := fmt.Sprintf("print-sorted-table-by-column-%d-desc-%t",
|
|
||||||
tt.sortby, tt.desc)
|
|
||||||
t.Run(testname, func(t *testing.T) {
|
|
||||||
SortByColumn = tt.sortby
|
|
||||||
SortDescending = tt.desc
|
|
||||||
|
|
||||||
printData(&tt.data)
|
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
|
||||||
n, err := reader.Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
buf = buf[:n]
|
|
||||||
output := strings.TrimSpace(string(buf))
|
|
||||||
|
|
||||||
if output != tt.expect {
|
|
||||||
t.Errorf("sort column: %d, got:\n%s\nwant:\n%s",
|
|
||||||
tt.sortby, output, tt.expect)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore
|
|
||||||
os.Stdout = origStdout
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSortByPrinter(t *testing.T) {
|
|
||||||
data := Tabdata{
|
|
||||||
maxwidthHeader: 8,
|
maxwidthHeader: 8,
|
||||||
maxwidthPerCol: []int{
|
maxwidthPerCol: []int{
|
||||||
5,
|
5,
|
||||||
@@ -278,74 +60,231 @@ func TestSortByPrinter(t *testing.T) {
|
|||||||
"06/Jan/2008 15:04:05 -0700",
|
"06/Jan/2008 15:04:05 -0700",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
sortby string
|
name string // so we can identify which one fails, can be the same
|
||||||
column int
|
// for multiple tests, because flags will be appended to the name
|
||||||
desc bool
|
sortby string // empty == default
|
||||||
expect string
|
column int // sort by this column, 0 == default first or NO Sort
|
||||||
}{
|
desc bool // sort in descending order, default == ascending
|
||||||
|
nonum bool // hide numbering
|
||||||
|
mode string // shell, orgtbl, etc. empty == default: ascii
|
||||||
|
usecol []int // columns to display, empty == display all
|
||||||
|
usecolstr string // for testname, must match usecol
|
||||||
|
expect string // rendered output we expect
|
||||||
|
}{
|
||||||
|
// --------------------- Default settings mode tests ``
|
||||||
{
|
{
|
||||||
|
mode: "ascii",
|
||||||
|
name: "default",
|
||||||
|
expect: `
|
||||||
|
NAME(1) DURATION(2) COUNT(3) WHEN(4)
|
||||||
|
beta 1d10h5m1s 33 3/1/2014
|
||||||
|
alpha 4h35m 170 2013-Feb-03
|
||||||
|
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default",
|
||||||
|
mode: "orgtbl",
|
||||||
|
expect: `
|
||||||
|
|---------+-------------+----------+----------------------------|
|
||||||
|
| NAME(1) | DURATION(2) | COUNT(3) | WHEN(4) |
|
||||||
|
|---------+-------------+----------+----------------------------|
|
||||||
|
| beta | 1d10h5m1s | 33 | 3/1/2014 |
|
||||||
|
| alpha | 4h35m | 170 | 2013-Feb-03 |
|
||||||
|
| ceta | 33d12h | 9 | 06/Jan/2008 15:04:05 -0700 |
|
||||||
|
|---------+-------------+----------+----------------------------|`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default",
|
||||||
|
mode: "markdown",
|
||||||
|
expect: `
|
||||||
|
| NAME(1) | DURATION(2) | COUNT(3) | WHEN(4) |
|
||||||
|
|---------|-------------|----------|----------------------------|
|
||||||
|
| beta | 1d10h5m1s | 33 | 3/1/2014 |
|
||||||
|
| alpha | 4h35m | 170 | 2013-Feb-03 |
|
||||||
|
| ceta | 33d12h | 9 | 06/Jan/2008 15:04:05 -0700 |`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default",
|
||||||
|
mode: "shell",
|
||||||
|
nonum: true,
|
||||||
|
expect: `
|
||||||
|
NAME="beta" DURATION="1d10h5m1s" COUNT="33" WHEN="3/1/2014"
|
||||||
|
NAME="alpha" DURATION="4h35m" COUNT="170" WHEN="2013-Feb-03"
|
||||||
|
NAME="ceta" DURATION="33d12h" COUNT="9" WHEN="06/Jan/2008 15:04:05 -0700"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default",
|
||||||
|
mode: "yaml",
|
||||||
|
nonum: true,
|
||||||
|
expect: `
|
||||||
|
entries:
|
||||||
|
- count: 33
|
||||||
|
duration: "1d10h5m1s"
|
||||||
|
name: "beta"
|
||||||
|
when: "3/1/2014"
|
||||||
|
- count: 170
|
||||||
|
duration: "4h35m"
|
||||||
|
name: "alpha"
|
||||||
|
when: "2013-Feb-03"
|
||||||
|
- count: 9
|
||||||
|
duration: "33d12h"
|
||||||
|
name: "ceta"
|
||||||
|
when: "06/Jan/2008 15:04:05 -0700"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default",
|
||||||
|
mode: "extended",
|
||||||
|
expect: `
|
||||||
|
NAME(1): beta
|
||||||
|
DURATION(2): 1d10h5m1s
|
||||||
|
COUNT(3): 33
|
||||||
|
WHEN(4): 3/1/2014
|
||||||
|
|
||||||
|
NAME(1): alpha
|
||||||
|
DURATION(2): 4h35m
|
||||||
|
COUNT(3): 170
|
||||||
|
WHEN(4): 2013-Feb-03
|
||||||
|
|
||||||
|
NAME(1): ceta
|
||||||
|
DURATION(2): 33d12h
|
||||||
|
COUNT(3): 9
|
||||||
|
WHEN(4): 06/Jan/2008 15:04:05 -0700`,
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------- UseColumns Tests FIXME: when we put
|
||||||
|
// these tests AFTER the sort tests, then the order of rows
|
||||||
|
// follows the last sort call (-k 4 here), even if we set
|
||||||
|
// SortByColumn to 0, which is also the default if unset in the
|
||||||
|
// test struct. Somehow the SliceStable() seens to modify the data
|
||||||
|
// structure, which seems impossible, since it's copied during
|
||||||
|
// every test run. So, I really don't understand the
|
||||||
|
// issue. However, I'll keep this for the moment, because this
|
||||||
|
// only seems to be a unit test related issue. In real use, the
|
||||||
|
// program exits after each call anyway - and it works everytime.
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "usecolumns",
|
||||||
|
usecol: []int{2, 4},
|
||||||
|
usecolstr: "2,4",
|
||||||
|
expect: `
|
||||||
|
DURATION(2) WHEN(4)
|
||||||
|
1d10h5m1s 3/1/2014
|
||||||
|
4h35m 2013-Feb-03
|
||||||
|
33d12h 06/Jan/2008 15:04:05 -0700`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "usecolumns",
|
||||||
|
usecol: []int{1, 4},
|
||||||
|
usecolstr: "1,4",
|
||||||
|
expect: `
|
||||||
|
NAME(1) WHEN(4)
|
||||||
|
beta 3/1/2014
|
||||||
|
alpha 2013-Feb-03
|
||||||
|
ceta 06/Jan/2008 15:04:05 -0700`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "usecolumns",
|
||||||
|
usecol: []int{2},
|
||||||
|
usecolstr: "2",
|
||||||
|
expect: `
|
||||||
|
DURATION(2)
|
||||||
|
1d10h5m1s
|
||||||
|
4h35m
|
||||||
|
33d12h`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "usecolumns",
|
||||||
|
usecol: []int{3},
|
||||||
|
usecolstr: "3",
|
||||||
|
expect: `
|
||||||
|
COUNT(3)
|
||||||
|
33
|
||||||
|
170
|
||||||
|
9`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "usecolumns",
|
||||||
|
column: 0,
|
||||||
|
usecol: []int{1, 3},
|
||||||
|
usecolstr: "1,3",
|
||||||
|
expect: `
|
||||||
|
NAME(1) COUNT(3)
|
||||||
|
beta 33
|
||||||
|
alpha 170
|
||||||
|
ceta 9`,
|
||||||
|
},
|
||||||
|
|
||||||
|
//------------------------ SORT TESTS
|
||||||
|
{
|
||||||
|
name: "sortbycolumn",
|
||||||
column: 3,
|
column: 3,
|
||||||
sortby: "numeric",
|
sortby: "numeric",
|
||||||
desc: false,
|
desc: false,
|
||||||
expect: `NAME(1) DURATION(2) COUNT(3) WHEN(4)
|
expect: `
|
||||||
|
NAME(1) DURATION(2) COUNT(3) WHEN(4)
|
||||||
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700
|
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700
|
||||||
beta 1d10h5m1s 33 3/1/2014
|
beta 1d10h5m1s 33 3/1/2014
|
||||||
alpha 4h35m 170 2013-Feb-03`,
|
alpha 4h35m 170 2013-Feb-03`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "sortbycolumn",
|
||||||
column: 2,
|
column: 2,
|
||||||
sortby: "duration",
|
sortby: "duration",
|
||||||
desc: false,
|
desc: false,
|
||||||
expect: `NAME(1) DURATION(2) COUNT(3) WHEN(4)
|
expect: `
|
||||||
|
NAME(1) DURATION(2) COUNT(3) WHEN(4)
|
||||||
alpha 4h35m 170 2013-Feb-03
|
alpha 4h35m 170 2013-Feb-03
|
||||||
beta 1d10h5m1s 33 3/1/2014
|
beta 1d10h5m1s 33 3/1/2014
|
||||||
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700`,
|
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "sortbycolumn",
|
||||||
column: 4,
|
column: 4,
|
||||||
sortby: "time",
|
sortby: "time",
|
||||||
desc: false,
|
desc: false,
|
||||||
expect: `NAME(1) DURATION(2) COUNT(3) WHEN(4)
|
expect: `
|
||||||
|
NAME(1) DURATION(2) COUNT(3) WHEN(4)
|
||||||
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700
|
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700
|
||||||
alpha 4h35m 170 2013-Feb-03
|
alpha 4h35m 170 2013-Feb-03
|
||||||
beta 1d10h5m1s 33 3/1/2014`,
|
beta 1d10h5m1s 33 3/1/2014`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrinter(t *testing.T) {
|
||||||
NoColor = true
|
NoColor = true
|
||||||
OutputMode = "ascii"
|
|
||||||
origStdout, reader := stdout2pipe(t)
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
testname := fmt.Sprintf("print-sorted-table-by-column-%d-desc-%t-sort-by-%s",
|
testname := fmt.Sprintf("print-sortcol-%d-desc-%t-sortby-%s-mode-%s-usecolumns-%s",
|
||||||
tt.column, tt.desc, tt.sortby)
|
tt.column, tt.desc, tt.sortby, tt.mode, tt.usecolstr)
|
||||||
|
|
||||||
t.Run(testname, func(t *testing.T) {
|
t.Run(testname, func(t *testing.T) {
|
||||||
|
// replaces os.Stdout, but we ignore it
|
||||||
|
var w bytes.Buffer
|
||||||
|
|
||||||
|
// cmd flags
|
||||||
SortByColumn = tt.column
|
SortByColumn = tt.column
|
||||||
SortDescending = tt.desc
|
SortDescending = tt.desc
|
||||||
SortMode = tt.sortby
|
SortMode = tt.sortby
|
||||||
|
OutputMode = tt.mode
|
||||||
|
NoNumbering = tt.nonum
|
||||||
|
UseColumns = tt.usecol
|
||||||
|
|
||||||
testdata := data
|
// the test checks the len!
|
||||||
printData(&testdata)
|
if len(tt.usecol) > 0 {
|
||||||
|
Columns = "yes"
|
||||||
buf := make([]byte, 1024)
|
} else {
|
||||||
n, err := reader.Read(buf)
|
Columns = ""
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
buf = buf[:n]
|
|
||||||
output := strings.TrimSpace(string(buf))
|
|
||||||
|
|
||||||
if output != tt.expect {
|
testdata := mockdata
|
||||||
t.Errorf("sort column: %d, sortby: %s, got:\n%s\nwant:\n%s",
|
output := strings.TrimSpace(printData(&w, &testdata))
|
||||||
tt.column, tt.sortby, output, tt.expect)
|
exp := strings.TrimSpace(tt.expect)
|
||||||
|
if output != exp {
|
||||||
|
t.Errorf("not rendered correctly:\n+++ got:\n%s\n+++ want:\n%s",
|
||||||
|
output, exp)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore
|
|
||||||
os.Stdout = origStdout
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func sortTable(data *Tabdata, col int) {
|
func sortTable(data *Tabdata, col int) {
|
||||||
if col <= 0 {
|
if SortByColumn <= 0 {
|
||||||
// no sorting wanted
|
// no sorting wanted
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user