Compare commits

...

13 Commits

Author SHA1 Message Date
08681756b6 v0.0.273 add stack to PanicWrappedErr
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m9s
2023-09-27 14:15:59 +02:00
64772d0474 v0.0.272 WMO: fix FindOneAndReplace not using FindOneAndReplace
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 50s
2023-09-26 14:41:15 +02:00
127764556e Merge branch 'master' of ssh://gogs.mikescher.com:8022/BlackForestBytes/goext 2023-09-26 14:41:06 +02:00
170f43d806 WMO: fix FindOneAndReplace not using FindOneAndReplace 2023-09-26 14:40:56 +02:00
9dffc41274 v0.0.271 return old value in AtomicBool::Set
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 53s
2023-09-26 14:32:45 +02:00
c63cf442f8 try to fix test 'cmdext:TestFailOnStderr'
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 39s
2023-09-25 18:04:56 +02:00
a2ba283632 v0.0.270 fix inversion of AssertDeepEqual
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 54s
2023-09-25 11:35:03 +02:00
4a1fb1ae18 fix inversion of AssertDeepEqual 2023-09-25 11:34:51 +02:00
a127b24e62 v0.0.269 add AssertSetDeepEqual
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m8s
2023-09-25 09:18:22 +02:00
69d6290376 add AssertSetDeepEqual 2023-09-25 09:18:07 +02:00
c08a739158 v0.0.268 added WeekStart() and WeekEnd()
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 50s
2023-09-21 16:29:23 +02:00
5f5f0e44f0 v0.0.267 fix AssertDeepEqual
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 50s
2023-09-21 14:15:02 +02:00
6e6797eac5 fix AssertDeepEqual 2023-09-21 14:14:51 +02:00
12 changed files with 108 additions and 24 deletions

View File

@@ -7,5 +7,11 @@ test:
which gotestsum || go install gotest.tools/gotestsum@latest which gotestsum || go install gotest.tools/gotestsum@latest
gotestsum --format "testname" -- -tags="timetzdata sqlite_fts5 sqlite_foreign_keys" "./..." gotestsum --format "testname" -- -tags="timetzdata sqlite_fts5 sqlite_foreign_keys" "./..."
test-in-docker:
tag="goext_temp_test_image:$(shell uuidgen | tr -d '-')"; \
docker build --tag $$tag . -f .gitea/workflows/Dockerfile_tests; \
docker run --rm $$tag; \
docker rmi $$tag
version: version:
_data/version.sh _data/version.sh

View File

@@ -133,9 +133,6 @@ func run(opt CommandRunner) (CommandResult, error) {
case <-stderrFailChan: case <-stderrFailChan:
_ = cmd.Process.Kill() _ = cmd.Process.Kill()
for _, lstr := range opt.listener {
lstr.Timeout()
}
if fallback, ok := syncext.ReadChannelWithTimeout(outputChan, 32*time.Millisecond); ok { if fallback, ok := syncext.ReadChannelWithTimeout(outputChan, 32*time.Millisecond); ok {
// most of the time the cmd.Process.Kill() should also have finished the pipereader // most of the time the cmd.Process.Kill() should also have finished the pipereader
@@ -160,7 +157,8 @@ func run(opt CommandRunner) (CommandResult, error) {
} }
case outobj := <-outputChan: case outobj := <-outputChan:
if exiterr, ok := outobj.err.(*exec.ExitError); ok { var exiterr *exec.ExitError
if errors.As(outobj.err, &exiterr) {
excode := exiterr.ExitCode() excode := exiterr.ExitCode()
for _, lstr := range opt.listener { for _, lstr := range opt.listener {
lstr.Finished(excode) lstr.Finished(excode)

View File

@@ -32,8 +32,8 @@ func (pr *pipeReader) Read(listener []CommandListener) (string, string, string,
stdout := "" stdout := ""
go func() { go func() {
buf := make([]byte, 128) buf := make([]byte, 128)
for true { for {
n, out := pr.stdout.Read(buf) n, err := pr.stdout.Read(buf)
if n > 0 { if n > 0 {
txt := string(buf[:n]) txt := string(buf[:n])
stdout += txt stdout += txt
@@ -42,11 +42,11 @@ func (pr *pipeReader) Read(listener []CommandListener) (string, string, string,
lstr.ReadRawStdout(buf[:n]) lstr.ReadRawStdout(buf[:n])
} }
} }
if out == io.EOF { if err == io.EOF {
break break
} }
if out != nil { if err != nil {
errch <- out errch <- err
break break
} }
} }
@@ -61,7 +61,7 @@ func (pr *pipeReader) Read(listener []CommandListener) (string, string, string,
stderr := "" stderr := ""
go func() { go func() {
buf := make([]byte, 128) buf := make([]byte, 128)
for true { for {
n, err := pr.stderr.Read(buf) n, err := pr.stderr.Read(buf)
if n > 0 { if n > 0 {

2
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/jmoiron/sqlx v1.3.5 github.com/jmoiron/sqlx v1.3.5
github.com/rs/xid v1.5.0 github.com/rs/xid v1.5.0
github.com/rs/zerolog v1.30.0 github.com/rs/zerolog v1.31.0
go.mongodb.org/mongo-driver v1.12.1 go.mongodb.org/mongo-driver v1.12.1
golang.org/x/crypto v0.13.0 golang.org/x/crypto v0.13.0
golang.org/x/sys v0.12.0 golang.org/x/sys v0.12.0

2
go.sum
View File

@@ -105,6 +105,8 @@ github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc=
github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU=
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

View File

@@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.266" const GoextVersion = "0.0.273"
const GoextVersionTimestamp = "2023-09-21T13:08:13+0200" const GoextVersionTimestamp = "2023-09-27T14:15:59+0200"

View File

@@ -1,7 +1,10 @@
package langext package langext
import "runtime/debug"
type PanicWrappedErr struct { type PanicWrappedErr struct {
panic any panic any
Stack string
} }
func (p PanicWrappedErr) Error() string { func (p PanicWrappedErr) Error() string {
@@ -15,7 +18,7 @@ func (p PanicWrappedErr) ReoveredObj() any {
func RunPanicSafe(fn func()) (err error) { func RunPanicSafe(fn func()) (err error) {
defer func() { defer func() {
if rec := recover(); rec != nil { if rec := recover(); rec != nil {
err = PanicWrappedErr{panic: rec} err = PanicWrappedErr{panic: rec, Stack: string(debug.Stack())}
} }
}() }()
@@ -27,7 +30,7 @@ func RunPanicSafe(fn func()) (err error) {
func RunPanicSafeR1(fn func() error) (err error) { func RunPanicSafeR1(fn func() error) (err error) {
defer func() { defer func() {
if rec := recover(); rec != nil { if rec := recover(); rec != nil {
err = PanicWrappedErr{panic: rec} err = PanicWrappedErr{panic: rec, Stack: string(debug.Stack())}
} }
}() }()
@@ -38,7 +41,7 @@ func RunPanicSafeR2[T1 any](fn func() (T1, error)) (r1 T1, err error) {
defer func() { defer func() {
if rec := recover(); rec != nil { if rec := recover(); rec != nil {
r1 = *new(T1) r1 = *new(T1)
err = PanicWrappedErr{panic: rec} err = PanicWrappedErr{panic: rec, Stack: string(debug.Stack())}
} }
}() }()
@@ -50,7 +53,7 @@ func RunPanicSafeR3[T1 any, T2 any](fn func() (T1, T2, error)) (r1 T1, r2 T2, er
if rec := recover(); rec != nil { if rec := recover(); rec != nil {
r1 = *new(T1) r1 = *new(T1)
r2 = *new(T2) r2 = *new(T2)
err = PanicWrappedErr{panic: rec} err = PanicWrappedErr{panic: rec, Stack: string(debug.Stack())}
} }
}() }()
@@ -63,7 +66,7 @@ func RunPanicSafeR4[T1 any, T2 any, T3 any](fn func() (T1, T2, T3, error)) (r1 T
r1 = *new(T1) r1 = *new(T1)
r2 = *new(T2) r2 = *new(T2)
r3 = *new(T3) r3 = *new(T3)
err = PanicWrappedErr{panic: rec} err = PanicWrappedErr{panic: rec, Stack: string(debug.Stack())}
} }
}() }()

View File

@@ -27,10 +27,12 @@ func (a *AtomicBool) Get() bool {
return a.v return a.v
} }
func (a *AtomicBool) Set(value bool) { func (a *AtomicBool) Set(value bool) bool {
a.lock.Lock() a.lock.Lock()
defer a.lock.Unlock() defer a.lock.Unlock()
oldValue := a.v
a.v = value a.v = value
for k, v := range a.listener { for k, v := range a.listener {
@@ -42,6 +44,8 @@ func (a *AtomicBool) Set(value bool) {
delete(a.listener, k) delete(a.listener, k)
} }
} }
return oldValue
} }
func (a *AtomicBool) Wait(waitFor bool) { func (a *AtomicBool) Wait(waitFor bool) {

28
timeext/calendarweek.go Normal file
View File

@@ -0,0 +1,28 @@
package timeext
import "time"
func WeekStart(year, week int) time.Time {
// https://stackoverflow.com/a/52303730/1761622
// Start from the middle of the year:
t := time.Date(year, 7, 1, 0, 0, 0, 0, time.UTC)
// Roll back to Monday:
if wd := t.Weekday(); wd == time.Sunday {
t = t.AddDate(0, 0, -6)
} else {
t = t.AddDate(0, 0, -int(wd)+1)
}
// Difference in weeks:
_, w := t.ISOWeek()
t = t.AddDate(0, 0, (week-w)*7)
return t
}
func WeekEnd(year, week int) time.Time {
return WeekStart(year, week).AddDate(0, 0, 7).Add(time.Duration(-1))
}

View File

@@ -0,0 +1,25 @@
package timeext
import (
"gogs.mikescher.com/BlackForestBytes/goext/tst"
"testing"
"time"
)
func TestWeekStart(t *testing.T) {
tst.AssertEqual(t, WeekStart(2018, 1).Format(time.RFC3339Nano), "2018-01-01T00:00:00Z")
tst.AssertEqual(t, WeekStart(2018, 2).Format(time.RFC3339Nano), "2018-01-08T00:00:00Z")
tst.AssertEqual(t, WeekStart(2019, 1).Format(time.RFC3339Nano), "2018-12-31T00:00:00Z")
tst.AssertEqual(t, WeekStart(2019, 2).Format(time.RFC3339Nano), "2019-01-07T00:00:00Z")
}
func TestWeekEnd(t *testing.T) {
tst.AssertEqual(t, WeekEnd(2018, 1).Format(time.RFC3339Nano), "2018-01-07T23:59:59.999999999Z")
tst.AssertEqual(t, WeekEnd(2018, 2).Format(time.RFC3339Nano), "2018-01-14T23:59:59.999999999Z")
tst.AssertEqual(t, WeekEnd(2019, 1).Format(time.RFC3339Nano), "2019-01-06T23:59:59.999999999Z")
tst.AssertEqual(t, WeekEnd(2019, 2).Format(time.RFC3339Nano), "2019-01-13T23:59:59.999999999Z")
}

View File

@@ -21,16 +21,34 @@ func AssertNotEqual[T comparable](t *testing.T, actual T, expected T) {
} }
} }
func AssertDeepEqual[T comparable](t *testing.T, actual T, expected T) { func AssertDeepEqual[T any](t *testing.T, actual T, expected T) {
t.Helper() t.Helper()
if reflect.DeepEqual(actual, expected) { if !reflect.DeepEqual(actual, expected) {
t.Errorf("values differ: Actual: '%v', Expected: '%v'", actual, expected) t.Errorf("values differ: Actual: '%v', Expected: '%v'", actual, expected)
} }
} }
func AssertNotDeepEqual[T comparable](t *testing.T, actual T, expected T) { func AssertSetDeepEqual[T any](t *testing.T, actual []T, expected []T) {
t.Helper() t.Helper()
if !reflect.DeepEqual(actual, expected) { if len(actual) != len(expected) {
t.Errorf("values differ in length: Actual (n=%d): '%v', Expected (n=%d): '%v'", len(actual), actual, len(expected), expected)
}
for _, a := range expected {
found := false
for _, b := range actual {
found = found || reflect.DeepEqual(a, b)
}
if !found {
t.Errorf("values differ: Element '%v' not found. Actual: '%v', Expected: '%v'", a, actual, expected)
return
}
}
}
func AssertNotDeepEqual[T any](t *testing.T, actual T, expected T) {
t.Helper()
if reflect.DeepEqual(actual, expected) {
t.Errorf("values do not differ: Actual: '%v', Expected: '%v'", actual, expected) t.Errorf("values do not differ: Actual: '%v', Expected: '%v'", actual, expected)
} }
} }

View File

@@ -73,7 +73,7 @@ func (c *Coll[TData]) ReplaceOne(ctx context.Context, filterQuery bson.M, value
} }
func (c *Coll[TData]) FindOneAndReplace(ctx context.Context, filterQuery bson.M, value TData) (TData, error) { func (c *Coll[TData]) FindOneAndReplace(ctx context.Context, filterQuery bson.M, value TData) (TData, error) {
mongoRes := c.coll.FindOneAndUpdate(ctx, filterQuery, bson.M{"$set": value}, options.FindOneAndUpdate().SetReturnDocument(options.After)) mongoRes := c.coll.FindOneAndReplace(ctx, filterQuery, value, options.FindOneAndReplace().SetReturnDocument(options.After))
if err := mongoRes.Err(); err != nil { if err := mongoRes.Err(); err != nil {
return *new(TData), exerr.Wrap(err, "mongo-query[find-one-and-update] failed"). return *new(TData), exerr.Wrap(err, "mongo-query[find-one-and-update] failed").
Str("collection", c.Name()). Str("collection", c.Name()).