From 6ce07c7506256c38ca8f52ef6191bf9054a62d50 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 17:57:25 +0100 Subject: [PATCH 01/13] add gh actions and templates, plus show-versions in Makefile --- .github/ISSUE_TEMPLATE/bug_report.md | 31 +++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 23 +++++++++++++++ .github/workflows/ci.yaml | 36 +++++++++++++++++++++++ Makefile | 12 ++++++++ 4 files changed, 102 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/ci.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..206efb5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,31 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[bug-report]" +labels: bug +assignees: TLINDEN + +--- + +**Describtion** + + + +**Steps To Reproduce** + + + +**Expected behavior** + + + +**Version information** + + + +**Additional informations** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..ed09312 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: Feature request +about: Suggest a feature +title: "[feature-request]" +labels: feature-request +assignees: TLINDEN + +--- + +**Describtion** + + + + +**Version information** + + diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..37998da --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,36 @@ +name: build-and-test-rpn +on: [push, pull_request] +jobs: + build: + strategy: + matrix: + version: [1.17, 1.18, 1.19] + os: [ubuntu-latest, windows-latest, macos-latest] + name: Build + runs-on: ${{ matrix.os }} + steps: + - name: Set up Go 1.18 + uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.version }} + id: go + + - name: checkout + uses: actions/checkout@v3 + + - name: build + run: make + + # - name: test + # run: make test + + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v3 + with: + go-version: 1.17 + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 diff --git a/Makefile b/Makefile index 24131eb..d306aad 100644 --- a/Makefile +++ b/Makefile @@ -77,3 +77,15 @@ buildall: release: buildall gh release create v$(VERSION) --generate-notes releases/* + +show-versions: buildlocal + @echo "### rpn version:" + @./rpn -v + + @echo + @echo "### go module versions:" + @go list -m all + + @echo + @echo "### go version used for building:" + @grep -m 1 go go.mod From c456cc1090f7f562c3ba13ec60629f4992b15c4b Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:01:00 +0100 Subject: [PATCH 02/13] force go 1.20 --- .github/workflows/ci.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 37998da..5167cd1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,12 +4,12 @@ jobs: build: strategy: matrix: - version: [1.17, 1.18, 1.19] + version: [1.20 1.21] os: [ubuntu-latest, windows-latest, macos-latest] name: Build runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.18 + - name: Set up Go 1.20 uses: actions/setup-go@v3 with: go-version: ${{ matrix.version }} @@ -30,7 +30,7 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.17 + go-version: 1.20 - uses: actions/checkout@v3 - name: golangci-lint uses: golangci/golangci-lint-action@v3 From 103dce21c1704f1b1e150b1a0c19b4931728c54c Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:03:43 +0100 Subject: [PATCH 03/13] fixed linting issues --- Makefile | 4 ---- calc.go | 45 --------------------------------------------- rpn.go | 14 -------------- 3 files changed, 63 deletions(-) diff --git a/Makefile b/Makefile index d306aad..aa3d3bd 100644 --- a/Makefile +++ b/Makefile @@ -39,10 +39,6 @@ ifdef HAVE_POD echo "var manpage = \`" >> $*.go pod2text $*.pod >> $*.go echo "\`" >> $*.go - - echo "var usage = \`" >> $*.go - awk '/SYNOPS/{f=1;next} /DESCR/{f=0} f' $*.pod | sed 's/^ //' >> $*.go - echo "\`" >> $*.go endif buildlocal: diff --git a/calc.go b/calc.go index be15743..c131a7d 100644 --- a/calc.go +++ b/calc.go @@ -20,7 +20,6 @@ package main import ( "errors" "fmt" - "math" "os" "regexp" "strconv" @@ -376,50 +375,6 @@ func (c *Calc) Debug(msg string) { } } -// do simple calculations -func (c *Calc) simple(op byte) { - c.stack.Backup() - - for c.stack.Len() > 1 { - b := c.stack.Pop() - a := c.stack.Pop() - var x float64 - - c.Debug(fmt.Sprintf("evaluating: %.2f %c %.2f", a, op, b)) - - switch op { - case '+': - x = a + b - case '-': - x = a - b - case 'x': - fallthrough // alias for * - case '*': - x = a * b - case '/': - if b == 0 { - fmt.Println("error: division by null!") - return - } - x = a / b - case '^': - x = math.Pow(a, b) - default: - panic("invalid operator!") - } - - c.stack.Push(x) - - c.History("%f %c %f = %f", a, op, b, x) - - if !c.batch { - break - } - } - - c.Result() -} - func (c *Calc) luafunc(funcname string) { // called from calc loop var x float64 diff --git a/rpn.go b/rpn.go index 1441cdb..8890af5 100644 --- a/rpn.go +++ b/rpn.go @@ -222,17 +222,3 @@ AUTHORS Thomas von Dein tom AT vondein DOT org ` -var usage = ` - -Usage: rpn [-bdvh] [] - -Options: - -b, --batchmode enable batch mode - -d, --debug enable debug mode - -v, --version show version - -h, --help show help - -When is given, batch mode ist automatically enabled. Use -this only when working with stdin. E.g.: echo "2 3 4 5" | rpn + - -` From 752deb8436a18475f5bad16ba97849de96881430 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:06:43 +0100 Subject: [PATCH 04/13] fix go versions --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5167cd1..6a9cbf5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,7 +4,7 @@ jobs: build: strategy: matrix: - version: [1.20 1.21] + version: [1.20, 1.21] os: [ubuntu-latest, windows-latest, macos-latest] name: Build runs-on: ${{ matrix.os }} From ee57f01635e7102a71f186d650df33da6ff2759b Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:11:29 +0100 Subject: [PATCH 05/13] try build --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6a9cbf5..20575f1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v3 - name: build - run: make + run: go build # - name: test # run: make test From 76f22987e0fba332f9ee9afd34ffdfefcc24c047 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:13:22 +0100 Subject: [PATCH 06/13] only 1.21 --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 20575f1..a7faf4c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,12 +4,12 @@ jobs: build: strategy: matrix: - version: [1.20, 1.21] + version: [1.21] os: [ubuntu-latest, windows-latest, macos-latest] name: Build runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.20 + - name: Set up Go uses: actions/setup-go@v3 with: go-version: ${{ matrix.version }} From fa4cd1639ff400bc4a3b7720fca3e82f91428206 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:16:46 +0100 Subject: [PATCH 07/13] try modules download --- .github/workflows/ci.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a7faf4c..59c4529 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,6 +27,8 @@ jobs: golangci: name: lint runs-on: ubuntu-latest + run: + modules-download-mode: vendor steps: - uses: actions/setup-go@v3 with: From 76b6f22c0c195d44c947e0d6eabd97b21516dd74 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:19:35 +0100 Subject: [PATCH 08/13] try 1.21 --- .github/workflows/ci.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 59c4529..146cf77 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,12 +27,10 @@ jobs: golangci: name: lint runs-on: ubuntu-latest - run: - modules-download-mode: vendor steps: - uses: actions/setup-go@v3 with: - go-version: 1.20 + go-version: 1.21 - uses: actions/checkout@v3 - name: golangci-lint uses: golangci/golangci-lint-action@v3 From 9a1c022d19f1179cd445fcaff5d75ebf4442b9be Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:21:38 +0100 Subject: [PATCH 09/13] +badges --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index eafd073..72149e1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +[![Actions](https://github.com/tlinden/rpnc/actions/workflows/ci.yaml/badge.svg)](https://github.com/tlinden/rpnc/actions) +[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://github.com/tlinden/rpnc/blob/master/LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/tlinden/rpnc)](https://goreportcard.com/report/github.com/tlinden/rpnc) + ## Reverse Polish Notation Calculator for the commandline This is a small commandline calculator which takes its input in From bf73697cac5fe464338d29739db3b4497c2a24f2 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:27:41 +0100 Subject: [PATCH 10/13] added test facilities --- Makefile | 1 - util_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 util_test.go diff --git a/Makefile b/Makefile index aa3d3bd..ac90935 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,6 @@ clean: test: go test -v ./... - bash t/test.sh singletest: @echo "Call like this: ''make singletest TEST=TestPrepareColumns MOD=lib" diff --git a/util_test.go b/util_test.go new file mode 100644 index 0000000..7c37735 --- /dev/null +++ b/util_test.go @@ -0,0 +1,32 @@ +/* +Copyright © 2023 Thomas von Dein + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +package main + +import ( + "testing" +) + +func TestContains(t *testing.T) { + list := []string{"a", "b", "c"} + + t.Run("contains", func(t *testing.T) { + if !contains(list, "a") { + t.Errorf("a in [a,b,c] not found") + } + }) +} From e7d18e5e721b66d3f06a140e7cadad90cb0a0e3f Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 5 Nov 2023 18:28:10 +0100 Subject: [PATCH 11/13] + test stage --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 146cf77..d9ceac6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,8 +21,8 @@ jobs: - name: build run: go build - # - name: test - # run: make test + - name: test + run: make test golangci: name: lint From 609275d2685272dc08c9824a75d40ba5df08fd4a Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 6 Nov 2023 14:37:20 +0100 Subject: [PATCH 12/13] added more tests --- calc_test.go | 141 +++++++++++++++++++++++++++++++++++++ stack_test.go | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 331 insertions(+) create mode 100644 calc_test.go create mode 100644 stack_test.go diff --git a/calc_test.go b/calc_test.go new file mode 100644 index 0000000..3ad864a --- /dev/null +++ b/calc_test.go @@ -0,0 +1,141 @@ +/* +Copyright © 2023 Thomas von Dein + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +package main + +import ( + "fmt" + "testing" +) + +func TestCalc(t *testing.T) { + calc := NewCalc() + + var tests = []struct { + name string + cmd string + exp float64 + batch bool + }{ + { + name: "plus", + cmd: `15 15 +`, + exp: 30, + }, + { + name: "power", + cmd: `4 2 ^`, + exp: 16, + }, + { + name: "minus", + cmd: `100 50 -`, + exp: 50, + }, + { + name: "multi", + cmd: `4 4 x`, + exp: 16, + }, + { + name: "divide", + cmd: `10 2 /`, + exp: 5, + }, + { + name: "percent", + cmd: `400 20 %`, + exp: 80, + }, + { + name: "percent-minus", + cmd: `400 20 %-`, + exp: 320, + }, + { + name: "percent-plus", + cmd: `400 20 %+`, + exp: 480, + }, + { + name: "mod", + cmd: `9 2 mod`, + exp: 1, + }, + { + name: "sqrt", + cmd: `16 sqrt`, + exp: 4, + }, + { + name: "ceil", + cmd: `15.5 ceil`, + exp: 16, + }, + { + name: "dim", + cmd: `6 4 dim`, + exp: 2, + }, + { + name: "batch-sum", + cmd: `2 2 2 2 sum`, + exp: 8, + batch: true, + }, + { + name: "batch-median", + cmd: `1 2 3 4 5 median`, + exp: 3, + batch: true, + }, + { + name: "batch-mean", + cmd: `2 2 8 2 2 mean`, + exp: 3.2, + batch: true, + }, + { + name: "batch-min", + cmd: `1 2 3 4 5 min`, + exp: 1, + batch: true, + }, + { + name: "batch-max", + cmd: `1 2 3 4 5 max`, + exp: 5, + batch: true, + }, + } + + for _, tt := range tests { + testname := fmt.Sprintf("cmd-%s-expect-%.2f", + tt.name, tt.exp) + + t.Run(testname, func(t *testing.T) { + calc.batch = tt.batch + calc.Eval(tt.cmd) + got := calc.Result() + calc.stack.Clear() + if got != tt.exp { + t.Errorf("calc failed:\n+++ got: %f\n--- want: %f", + got, tt.exp) + } + }) + } +} diff --git a/stack_test.go b/stack_test.go new file mode 100644 index 0000000..aa83e96 --- /dev/null +++ b/stack_test.go @@ -0,0 +1,190 @@ +/* +Copyright © 2023 Thomas von Dein + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +package main + +import ( + "testing" +) + +func TestPush(t *testing.T) { + t.Run("push", func(t *testing.T) { + s := NewStack() + s.Push(5) + + if s.linklist.Back().Value != 5.0 { + t.Errorf("push failed:\n+++ got: %f\n--- want: %f", + s.linklist.Back().Value, 5.0) + } + }) +} + +func TestPop(t *testing.T) { + t.Run("pop", func(t *testing.T) { + s := NewStack() + s.Push(5) + got := s.Pop() + + if got != 5.0 { + t.Errorf("pop failed:\n+++ got: %f\n--- want: %f", + got, 5.0) + } + + if s.Len() != 0 { + t.Errorf("stack not empty after pop()") + } + }) +} + +func TestPops(t *testing.T) { + t.Run("pops", func(t *testing.T) { + s := NewStack() + s.Push(5) + s.Push(5) + s.Push(5) + s.Pop() + + if s.Len() != 2 { + t.Errorf("stack len not correct after pop:\n+++ got: %d\n--- want: %d", + s.Len(), 2) + } + }) +} + +func TestShift(t *testing.T) { + t.Run("shift", func(t *testing.T) { + s := NewStack() + s.Shift() + + if s.Len() != 0 { + t.Errorf("stack not empty after shift()") + } + }) +} + +func TestClear(t *testing.T) { + t.Run("clear", func(t *testing.T) { + s := NewStack() + s.Push(5) + s.Push(5) + s.Push(5) + s.Clear() + + if s.Len() != 0 { + t.Errorf("stack not empty after clear()") + } + }) +} + +func TestLast(t *testing.T) { + t.Run("last", func(t *testing.T) { + s := NewStack() + s.Push(5) + got := s.Last() + + if len(got) != 1 { + t.Errorf("last failed:\n+++ got: %d elements\n--- want: %d elements", + len(got), 1) + } + + if got[0] != 5.0 { + t.Errorf("last failed:\n+++ got: %f\n--- want: %f", + got, 5.0) + } + + if s.Len() != 1 { + t.Errorf("stack modified after last()") + } + }) +} + +func TestAll(t *testing.T) { + t.Run("all", func(t *testing.T) { + s := NewStack() + list := []float64{2, 4, 6, 8} + + for _, item := range list { + s.Push(item) + } + + got := s.All() + + if len(got) != len(list) { + t.Errorf("all failed:\n+++ got: %d elements\n--- want: %d elements", + len(got), len(list)) + } + + for i := 1; i < len(list); i++ { + if got[i] != list[i] { + t.Errorf("all failed (element %d):\n+++ got: %f\n--- want: %f", + i, got[i], list[i]) + } + } + + if s.Len() != len(list) { + t.Errorf("stack modified after last()") + } + }) +} + +func TestBackupRestore(t *testing.T) { + t.Run("shift", func(t *testing.T) { + s := NewStack() + s.Push(5) + s.Backup() + s.Clear() + s.Restore() + + if s.Len() != 1 { + t.Errorf("stack not correctly restored()") + } + + a := s.Pop() + if a != 5.0 { + t.Errorf("stack not identical to old revision:\n+++ got: %f\n--- want: %f", + a, 5.0) + } + }) +} + +func TestReverse(t *testing.T) { + t.Run("reverse", func(t *testing.T) { + s := NewStack() + list := []float64{2, 4, 6} + reverse := []float64{6, 4, 2} + + for _, item := range list { + s.Push(item) + } + + s.Reverse() + + got := s.All() + + if len(got) != len(list) { + t.Errorf("all failed:\n+++ got: %d elements\n--- want: %d elements", + len(got), len(list)) + } + + for i := 1; i < len(reverse); i++ { + if got[i] != reverse[i] { + t.Errorf("reverse failed (element %d):\n+++ got: %f\n--- want: %f", + i, got[i], list[i]) + } + } + }) +} From 620f2740118d7a2e1957127900a340a667eea606 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 6 Nov 2023 14:56:51 +0100 Subject: [PATCH 13/13] ignore coverage report --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ed13d1c..7f33a39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ releases rpn rpn.1 +coverage.out