Compare commits

...

20 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
cd9406900a v0.0.266 fix tst showing wrong file:line
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m22s
2023-09-21 13:08:13 +02:00
6c81f7f6bc fix tst showing wrong file:line, add DeepEqual 2023-09-21 13:07:55 +02:00
d56a0235af v0.0.265 add ListWithCount
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 49s
2023-09-18 12:57:27 +02:00
de2ca763c1 add function for ListWithCount 2023-09-18 12:56:56 +02:00
da52bb5c90 v0.0.264 added Valid() to id-gen
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 49s
2023-09-18 11:46:17 +02:00
3d4afe7b25 v0.0.263 re-add checksum guard to id-generate
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 50s
2023-09-18 10:43:29 +02:00
f5766d639c v0.0.262 ignore _gen files in bfcodegen checksum-calc
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 46s
2023-09-18 10:42:43 +02:00
15 changed files with 154 additions and 22 deletions

View File

@@ -7,5 +7,11 @@ test:
which gotestsum || go install gotest.tools/gotestsum@latest
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:
_data/version.sh

View File

@@ -59,6 +59,7 @@ func GenerateEnumSpecs(sourceDir string, destFile string) error {
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return v.Name() != path.Base(destFile) })
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return strings.HasSuffix(v.Name(), ".go") })
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return !strings.HasSuffix(v.Name(), "_gen.go") })
langext.SortBy(files, func(v os.DirEntry) string { return v.Name() })
newChecksumStr := goext.GoextVersion

View File

@@ -49,6 +49,7 @@ func GenerateIDSpecs(sourceDir string, destFile string) error {
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return v.Name() != path.Base(destFile) })
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return strings.HasSuffix(v.Name(), ".go") })
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return !strings.HasSuffix(v.Name(), "_gen.go") })
langext.SortBy(files, func(v os.DirEntry) string { return v.Name() })
newChecksumStr := goext.GoextVersion
@@ -66,7 +67,7 @@ func GenerateIDSpecs(sourceDir string, destFile string) error {
fmt.Printf("[IDGenerate] Checksum has changed ( %s -> %s ), will generate new file\n\n", oldChecksum, newChecksum)
} else {
fmt.Printf("[IDGenerate] Checksum unchanged ( %s ), nothing to do\n", oldChecksum)
//TODO return nil
return nil
}
allIDs := make([]IDDef, 0)
@@ -208,6 +209,13 @@ func fmtIDOutput(cs string, ids []IDDef, pkgname string) string {
str += "" + "\n"
str += "func (i " + iddef.Name + ") Valid() bool {" + "\n"
str += " _, err := primitive.ObjectIDFromHex(string(i))" + "\n"
str += " return err == nil" + "\n"
str += "}" + "\n"
str += "" + "\n"
if anyDef != nil {
str += "func (i " + iddef.Name + ") AsAny() " + anyDef.Name + " {" + "\n"
str += " return " + anyDef.Name + "(i)" + "\n"

View File

@@ -133,9 +133,6 @@ func run(opt CommandRunner) (CommandResult, error) {
case <-stderrFailChan:
_ = cmd.Process.Kill()
for _, lstr := range opt.listener {
lstr.Timeout()
}
if fallback, ok := syncext.ReadChannelWithTimeout(outputChan, 32*time.Millisecond); ok {
// 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:
if exiterr, ok := outobj.err.(*exec.ExitError); ok {
var exiterr *exec.ExitError
if errors.As(outobj.err, &exiterr) {
excode := exiterr.ExitCode()
for _, lstr := range opt.listener {
lstr.Finished(excode)

View File

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

4
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/gin-gonic/gin v1.9.1
github.com/jmoiron/sqlx v1.3.5
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
golang.org/x/crypto v0.13.0
golang.org/x/sys v0.12.0
@@ -25,7 +25,7 @@ require (
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect

4
go.sum
View File

@@ -58,6 +58,8 @@ github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQ
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@@ -103,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.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

View File

@@ -1,5 +1,5 @@
package goext
const GoextVersion = "0.0.261"
const GoextVersion = "0.0.273"
const GoextVersionTimestamp = "2023-09-18T10:38:25+0200"
const GoextVersionTimestamp = "2023-09-27T14:15:59+0200"

View File

@@ -1,7 +1,10 @@
package langext
import "runtime/debug"
type PanicWrappedErr struct {
panic any
Stack string
}
func (p PanicWrappedErr) Error() string {
@@ -15,7 +18,7 @@ func (p PanicWrappedErr) ReoveredObj() any {
func RunPanicSafe(fn func()) (err error) {
defer func() {
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) {
defer func() {
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() {
if rec := recover(); rec != nil {
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 {
r1 = *new(T1)
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)
r2 = *new(T2)
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
}
func (a *AtomicBool) Set(value bool) {
func (a *AtomicBool) Set(value bool) bool {
a.lock.Lock()
defer a.lock.Unlock()
oldValue := a.v
a.v = value
for k, v := range a.listener {
@@ -42,6 +44,8 @@ func (a *AtomicBool) Set(value bool) {
delete(a.listener, k)
}
}
return oldValue
}
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

@@ -2,23 +2,59 @@ package tst
import (
"encoding/hex"
"reflect"
"runtime/debug"
"testing"
)
func AssertEqual[T comparable](t *testing.T, actual T, expected T) {
t.Helper()
if actual != expected {
t.Errorf("values differ: Actual: '%v', Expected: '%v'", actual, expected)
}
}
func AssertNotEqual[T comparable](t *testing.T, actual T, expected T) {
t.Helper()
if actual == expected {
t.Errorf("values do not differ: Actual: '%v', Expected: '%v'", actual, expected)
}
}
func AssertDeepEqual[T any](t *testing.T, actual T, expected T) {
t.Helper()
if !reflect.DeepEqual(actual, expected) {
t.Errorf("values differ: Actual: '%v', Expected: '%v'", actual, expected)
}
}
func AssertSetDeepEqual[T any](t *testing.T, actual []T, expected []T) {
t.Helper()
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)
}
}
func AssertDeRefEqual[T comparable](t *testing.T, actual *T, expected T) {
t.Helper()
if actual == nil {
t.Errorf("values differ: Actual: NIL, Expected: '%v'", expected)
}
@@ -28,6 +64,7 @@ func AssertDeRefEqual[T comparable](t *testing.T, actual *T, expected T) {
}
func AssertPtrEqual[T comparable](t *testing.T, actual *T, expected *T) {
t.Helper()
if actual == nil && expected == nil {
return
}
@@ -47,6 +84,7 @@ func AssertPtrEqual[T comparable](t *testing.T, actual *T, expected *T) {
}
func AssertHexEqual(t *testing.T, expected string, actual []byte) {
t.Helper()
actualStr := hex.EncodeToString(actual)
if actualStr != expected {
t.Errorf("values differ: Actual: '%v', Expected: '%v'", actualStr, expected)
@@ -54,18 +92,21 @@ func AssertHexEqual(t *testing.T, expected string, actual []byte) {
}
func AssertTrue(t *testing.T, value bool) {
t.Helper()
if !value {
t.Error("value should be true\n" + string(debug.Stack()))
}
}
func AssertFalse(t *testing.T, value bool) {
t.Helper()
if value {
t.Error("value should be false\n" + string(debug.Stack()))
}
}
func AssertNoErr(t *testing.T, anerr error) {
t.Helper()
if anerr != nil {
t.Error("Function returned an error: " + anerr.Error() + "\n" + string(debug.Stack()))
}

View File

@@ -116,3 +116,17 @@ func (c *Coll[TData]) Count(ctx context.Context, filter ct.Filter) (int64, error
return 0, nil
}
func (c *Coll[TData]) ListWithCount(ctx context.Context, filter ct.Filter, pageSize *int, inTok ct.CursorToken) ([]TData, ct.CursorToken, int64, error) {
// NOTE: Possible optimization: Cache count in CursorToken, then fetch count only on first page.
count, err := c.Count(ctx, filter)
if err != nil {
return nil, ct.CursorToken{}, 0, err
}
data, token, err := c.List(ctx, filter, pageSize, inTok)
if err != nil {
return nil, ct.CursorToken{}, 0, err
}
return data, token, count, nil
}

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) {
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 {
return *new(TData), exerr.Wrap(err, "mongo-query[find-one-and-update] failed").
Str("collection", c.Name()).