Skip to content

Commit 035a755

Browse files
authored
Merge pull request #17 from lainio/v0-9-40
v0 9 40
2 parents 76832c3 + 7c6609d commit 035a755

33 files changed

+876
-222
lines changed

.github/workflows/test.yml

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,39 @@ jobs:
55
name: lint
66
runs-on: ubuntu-latest
77
steps:
8-
- uses: actions/checkout@v3
9-
- name: golangci-lint
10-
uses: golangci/golangci-lint-action@v2
11-
with:
12-
version: latest
13-
args: --timeout=5m
8+
- uses: actions/checkout@v3
9+
- name: golangci-lint
10+
uses: golangci/golangci-lint-action@v2
11+
with:
12+
version: latest
13+
args: --timeout=5m
1414
test:
15+
strategy:
16+
matrix:
17+
go-version: [1.18.x, 1.19.x, 1.20.x, 1.21.x]
18+
os: [windows-latest, ubuntu-latest, macos-latest]
19+
runs-on: ${{ matrix.os }}
20+
steps:
21+
- name: setup go
22+
uses: actions/setup-go@v2
23+
with:
24+
go-version: ${{ matrix.go-version }}
25+
- name: checkout
26+
uses: actions/checkout@v2
27+
- name: test
28+
run: make test
29+
test-cov:
1530
runs-on: ubuntu-latest
1631
steps:
17-
- name: setup
18-
uses: actions/setup-go@v2
19-
with:
20-
go-version: 1.19.x
21-
- name: checkout
22-
uses: actions/checkout@v2
23-
- name: test
24-
run: make test_cov_out
25-
- name: upload
26-
uses: codecov/codecov-action@v2
27-
with:
28-
files: ./coverage.txt
32+
- name: setup
33+
uses: actions/setup-go@v2
34+
with:
35+
go-version: 1.19.x
36+
- name: checkout
37+
uses: actions/checkout@v2
38+
- name: test
39+
run: make test_cov_out
40+
- name: upload
41+
uses: codecov/codecov-action@v2
42+
with:
43+
files: ./coverage.txt

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ coverage.*
1515

1616
# Output of the go coverage tool, specifically when used with LiteIDE
1717
*.out
18+
19+
dist/

.goreleaser.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# This is an example .goreleaser.yml file with some sensible defaults.
2+
# Make sure to check the documentation at https://goreleaser.com
3+
before:
4+
hooks:
5+
# You may remove this if you don't use go modules.
6+
- go mod tidy
7+
# you may remove this if you don't need go generate
8+
- go generate ./...
9+
builds:
10+
- skip: true
11+
12+
changelog:
13+
sort: asc
14+
filters:
15+
exclude:
16+
- '^docs:'
17+
- '^test:'
18+
19+
# The lines beneath this are called `modelines`. See `:help modeline`
20+
# Feel free to remove those if you don't want/use them.
21+
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
22+
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Cangelog
1+
## Changelog
22

33
### Version history
44

Makefile

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ PKG_ERR2 := github.com/lainio/err2
44
PKG_ASSERT := github.com/lainio/err2/assert
55
PKG_TRY := github.com/lainio/err2/try
66
PKG_DEBUG := github.com/lainio/err2/internal/debug
7+
PKG_HANDLER := github.com/lainio/err2/internal/handler
78
PKG_STR := github.com/lainio/err2/internal/str
89
PKG_X := github.com/lainio/err2/internal/x
9-
PKGS := $(PKG_ERR2) $(PKG_ASSERT) $(PKG_TRY) $(PKG_DEBUG) $(PKG_STR) $(PKG_X)
10+
PKGS := $(PKG_ERR2) $(PKG_ASSERT) $(PKG_TRY) $(PKG_DEBUG) $(PKG_HANDLER) $(PKG_STR) $(PKG_X)
1011

1112
SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS))
1213

@@ -29,50 +30,71 @@ test_try:
2930
test_debug:
3031
$(GO) test $(TEST_ARGS) $(PKG_DEBUG)
3132

33+
test_handler:
34+
$(GO) test $(TEST_ARGS) $(PKG_HANDLER)
35+
3236
test_str:
3337
$(GO) test $(TEST_ARGS) $(PKG_STR)
3438

3539
test_x:
3640
$(GO) test $(TEST_ARGS) $(PKG_X)
3741

42+
testv:
43+
$(GO) test -v $(TEST_ARGS) $(PKGS)
44+
3845
test:
3946
$(GO) test $(TEST_ARGS) $(PKGS)
4047

48+
inline_err2:
49+
$(GO) test -c -gcflags=-m=2 $(PKG_ERR2) 2>&1 | ag 'inlin'
50+
51+
tinline_err2:
52+
$(GO) test -c -gcflags=-m=2 $(PKG_ERR2) 2>&1 | ag 'inlin' | ag 'err2_test'
53+
54+
inline_handler:
55+
$(GO) test -c -gcflags=-m=2 $(PKG_HANDLER) 2>&1 | ag 'inlin'
56+
57+
tinline_handler:
58+
$(GO) test -c -gcflags=-m=2 $(PKG_HANDLER) 2>&1 | ag 'inlin'
59+
4160
bench:
42-
$(GO) test -bench=. $(PKGS)
61+
$(GO) test $(TEST_ARGS) -bench=. $(PKGS)
4362

4463
bench_goid:
45-
$(GO) test -bench='BenchmarkGoid' $(PKG_ASSERT)
64+
$(GO) test $(TEST_ARGS) -bench='BenchmarkGoid' $(PKG_ASSERT)
65+
66+
bench_reca:
67+
$(GO) test $(TEST_ARGS) -bench='BenchmarkRecursion.*' $(PKG_ERR2)
4668

4769
bench_out:
48-
$(GO) test -bench='BenchmarkTryOut_.*' $(PKG_ERR2)
70+
$(GO) test $(TEST_ARGS) -bench='BenchmarkTryOut_.*' $(PKG_ERR2)
4971

5072
bench_go:
51-
$(GO) test -bench='BenchmarkTry_StringGenerics' $(PKG_ERR2)
52-
53-
bench_arec:
54-
$(GO) test -bench='BenchmarkRecursion.*' $(PKG_ERR2)
73+
$(GO) test $(TEST_ARGS) -bench='BenchmarkTry_StringGenerics' $(PKG_ERR2)
5574

5675
bench_that:
57-
$(GO) test -bench='BenchmarkThat.*' $(PKG_ASSERT)
76+
$(GO) test $(TEST_ARGS) -bench='BenchmarkThat.*' $(PKG_ASSERT)
5877

5978
bench_copy:
60-
$(GO) test -bench='Benchmark_CopyBuffer' $(PKG_TRY)
79+
$(GO) test $(TEST_ARGS) -bench='Benchmark_CopyBuffer' $(PKG_TRY)
80+
81+
bench_rece:
82+
$(GO) test $(TEST_ARGS) -bench='BenchmarkRecursionWithTryAnd_Empty_Defer' $(PKG_ERR2)
6183

6284
bench_rec:
63-
$(GO) test -bench='BenchmarkRecursionWithOldErrorIfCheckAnd_Defer' $(PKG_ERR2)
85+
$(GO) test $(TEST_ARGS) -bench='BenchmarkRecursionWithOldErrorIfCheckAnd_Defer' $(PKG_ERR2)
6486

6587
bench_err2:
66-
$(GO) test -bench=. $(PKG_ERR2)
88+
$(GO) test $(TEST_ARGS) -bench=. $(PKG_ERR2)
6789

6890
bench_assert:
69-
$(GO) test -bench=. $(PKG_ASSERT)
91+
$(GO) test $(TEST_ARGS) -bench=. $(PKG_ASSERT)
7092

7193
bench_str:
72-
$(GO) test -bench=. $(PKG_STR)
94+
$(GO) test $(TEST_ARGS) -bench=. $(PKG_STR)
7395

7496
bench_x:
75-
$(GO) test -bench=. $(PKG_X)
97+
$(GO) test $(TEST_ARGS) -bench=. $(PKG_X)
7698

7799
vet: | test
78100
$(GO) vet $(PKGS)

README.md

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ func CopyFile(src, dst string) (err error) {
2424
if err != nil {
2525
return fmt.Errorf("mixing traditional error checking: %w", err)
2626
}
27-
defer err2.Handle(&err, func() {
28-
os.Remove(dst)
29-
})
27+
defer err2.Handle(&err, err2.Err(func(error) {
28+
try.Out1(os.Remove(dst)).Logf("cleaning error")
29+
}))
3030
defer w.Close()
3131
try.To1(io.Copy(w, r))
3232
return nil
@@ -254,7 +254,8 @@ We also mark functions deprecated before they become obsolete. Usually, one
254254
released version before. We have tested this with a large code base in our
255255
systems, and it works wonderfully.
256256
257-
More information can be found in the scripts' [readme file](./scripts/README.md).
257+
More information can be found in the `scripts/` directory [readme
258+
file](./scripts/README.md).
258259
259260
## Assertion
260261
@@ -429,18 +430,41 @@ Please see the full version history from [CHANGELOG](./CHANGELOG.md).
429430
430431
### Latest Release
431432
432-
##### 0.9.29
433-
- New API for immediate error handling: `try out handle/catch err`
434-
```go
435-
val := try.Out1(strconv.Atoi(s)).Catch(10)
436-
```
437-
- New err2.Catch API for automatic logging
438-
- Performance boost for assert pkg: `defer assert.PushTester(t)()`
439-
- Our API has now *all the same features Zig's error handling has*
433+
##### 0.9.40
434+
- Significant performance boost for: `defer err2.Handle/Catch()`
435+
- **3x faster happy path than the previous version, which is now equal to
436+
simplest `defer` function in the `err`-returning function** . (Please see
437+
the `defer` benchmarks in the `err2_test.go` and run `make bench_reca`)
438+
- the solution caused a change to API, where the core reason is Go's
439+
optimization "bug". (We don't have confirmation yet.)
440+
- Changed API for deferred error handling: `defer err2.Handle/Catch()`
441+
- *Obsolete*:
442+
```go
443+
defer err2.Handle(&err, func() {}) // <- relaying closure to access err val
444+
```
445+
- Current version:
446+
```go
447+
defer err2.Handle(&err, func(err error) error { return err }) // not a closure
448+
```
449+
Because handler function is not relaying closures any more, it opens a new
450+
opportunity to use and build general helper functions: `err2.Noop`, etc.
451+
- Use auto-migration scripts especially for large code-bases. More information
452+
can be found in the `scripts/` directory's [readme file](./scripts/README.md).
453+
- Added a new (*experimental*) API:
454+
```go
455+
defer err2.Handle(&err, func(noerr bool) {
456+
assert.That(noerr) // noerr is always true!!
457+
doSomething()
458+
})
459+
```
460+
This is experimental because we aren't sure if this is something we want to
461+
have in the `err2` package.
462+
- Bug fixes: `ResultX.Logf()` now works as it should
463+
- More documentation
440464
441465
### Upcoming releases
442466
443-
##### 0.9.3
444-
- Go's standard lib's flag pkg integration (similar to `glog`)
467+
##### 0.9.5
468+
- Idea: Go's standard lib's flag pkg integration (similar to `glog`)
445469
- Continue removing unused parts from `assert` pkg
446470
- More documentation, repairing for some sort of marketing

assert/assert.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,52 @@ import (
1616
type defInd = uint32
1717

1818
const (
19+
// Production is the best asserter for most uses. The assertion violations
20+
// are treated as Go error values. And only a pragmatic caller info is
21+
// automatically included into the error message like file name, line
22+
// number, and caller function.
1923
Production defInd = 0 + iota
24+
25+
// Development is the best asserter for most development uses. The
26+
// assertion violations are treated as Go error values. And a formatted
27+
// caller info is automatically included to the error message like file
28+
// name, line number, and caller function.
2029
Development
30+
31+
// Test minimalistic asserter for unit test use. More pragmatic is the
32+
// TestFull asserter (default).
33+
//
34+
// Use this asserter if your IDE/editor doesn't support long file names, or
35+
// for temporary problem solving for your programming environment.
2136
Test
37+
38+
// TestFull asserter (default). The TestFull asserter includes caller info
39+
// and call stack for unit testing, similarly like err2's error traces.
40+
//
41+
// The call stack produced by the test asserts can be used over Go module
42+
// boundaries. For example, if your app and it's sub packages both use
43+
// err2/assert for unit testing and runtime checks, the runtime assertions
44+
// will be automatically converted to test asserts on the fly. If any of
45+
// the runtime asserts in sub packages fails during the app tests, the
46+
// current app test fails too.
47+
//
48+
// Note, that the cross-module assertions produce long file names (path
49+
// included), and some of the Go test result parsers cannot handle that.
50+
// A proper test result parser like 'github.com/lainio/nvim-go' (fork)
51+
// works very well. Also most of the make result parsers can process the
52+
// output properly and allow traverse of locations of the error trace.
2253
TestFull
54+
55+
// Debug asserter transforms assertion violations to panics which is the
56+
// patter that e.g. Go's standard library uses:
57+
//
58+
// if p == nil {
59+
// panic("pkg: ptr cannot be nil")
60+
// }
61+
//
62+
// is equal to:
63+
//
64+
// assert.NotNil(p)
2365
Debug
2466
)
2567

@@ -93,14 +135,18 @@ const (
93135
//
94136
// Because PushTester returns PopTester it allows us to merge these two calls to
95137
// one line. See the first t.Run call. NOTE. More information in PopTester.
138+
//
139+
// PushTester allows you to change the current default asserter by accepting it
140+
// as a second argument. NOTE. That it change the default asserter for whole
141+
// package. The argument is mainly for temporary development use and isn't not
142+
// preferrred API usage.
96143
func PushTester(t testing.TB, a ...defInd) function {
97144
if len(a) > 0 {
98145
SetDefault(a[0])
99146
} else if Default()&AsserterUnitTesting == 0 {
100147
// if this is forgotten or tests don't have proper place to set it
101148
// it's good to keep the API as simple as possible
102-
SetDefault(Test)
103-
// TODO: parallel testing is something we should test.
149+
SetDefault(TestFull)
104150
}
105151
testers.Tx(func(m testersMap) {
106152
rid := goid()

assert/assert_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func ExampleThat() {
1818
}
1919
err := sample()
2020
fmt.Printf("%v", err)
21-
// Output: testing run example: assertion test
21+
// Output: testing: run example: assertion test
2222
}
2323

2424
func ExampleNotNil() {

doc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ them. The CopyFile example shows how it works:
3434
w := try.To1(os.Create(dst))
3535
// Add error handler to clean up the destination file. Place it here that
3636
// the next deferred close is called before our Remove call.
37-
defer err2.Handle(&err, func() {
37+
defer err2.Handle(&err, err2.Err(func(error) {
3838
os.Remove(dst)
39-
})
39+
}))
4040
defer w.Close()
4141
4242
// Try to copy the file. If error occurs now, all previous error handlers

0 commit comments

Comments
 (0)