Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
infastin committed Jul 2, 2024
2 parents 79c4b3b + 7de405e commit f1e5a30
Show file tree
Hide file tree
Showing 20 changed files with 481 additions and 81 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.18.x, 1.19.x, 1.20.x, 1.21.x]
go-version: [1.20.x, 1.21.x, 1.22.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 10
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
linters:
strategy:
matrix:
go-version: [1.21.x]
go-version: [1.22.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 10
Expand All @@ -35,5 +35,5 @@ jobs:
- name: lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.55.1
version: v1.57.2
args: --print-resources-usage --timeout=10m --verbose
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

# NOTE: This Makefile is only necessary if you
# NOTE: This Makefile is only necessary if you
# plan on developing the msgp tool and library.
# Installation can still be performed with a
# normal `go install`.
Expand Down Expand Up @@ -55,8 +55,8 @@ ci: prepare
if [ `arch` == 'x86_64' ]; then \
sudo apt-get -y -q update; \
sudo apt-get -y -q install build-essential; \
wget -q https://github.com/tinygo-org/tinygo/releases/download/v0.30.0/tinygo_0.30.0_amd64.deb; \
sudo dpkg -i tinygo_0.30.0_amd64.deb; \
wget -q https://github.com/tinygo-org/tinygo/releases/download/v0.32.0/tinygo_0.32.0_amd64.deb; \
sudo dpkg -i tinygo_0.32.0_amd64.deb; \
export PATH=$$PATH:/usr/local/tinygo/bin; \
fi
go test -v ./... ./_generated
9 changes: 9 additions & 0 deletions _generated/custom_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package _generated

//go:generate msgp
//msgp:tag mytag

type CustomTag struct {
Foo string `mytag:"foo_custom_name"`
Bar int `mytag:"bar1234"`
}
64 changes: 64 additions & 0 deletions _generated/custom_tag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package _generated

import (
"encoding/json"
"fmt"
"reflect"
"testing"

"bytes"

"github.com/tinylib/msgp/msgp"
)

func TestCustomTag(t *testing.T) {
t.Run("File Scope", func(t *testing.T) {
ts := CustomTag{
Foo: "foostring13579",
Bar: 999_999}
encDecCustomTag(t, ts, "mytag")
})
}

func encDecCustomTag(t *testing.T, testStruct msgp.Encodable, tag string) {
var b bytes.Buffer
msgp.Encode(&b, testStruct)

// Check tag names using JSON as an intermediary layer
// TODO: is there a way to avoid the JSON layer? We'd need to directly decode raw msgpack -> map[string]any
refJSON, err := json.Marshal(testStruct)
if err != nil {
t.Error(fmt.Sprintf("error encoding struct as JSON: %v", err))
}
ref := make(map[string]any)
// Encoding and decoding the original struct via JSON is necessary
// for field comparisons to work, since JSON -> map[string]any
// relies on type inferences such as all numbers being float64s
json.Unmarshal(refJSON, &ref)

var encJSON bytes.Buffer
msgp.UnmarshalAsJSON(&encJSON, b.Bytes())
encoded := make(map[string]any)
json.Unmarshal(encJSON.Bytes(), &encoded)

tsType := reflect.TypeOf(testStruct)
for i := 0; i < tsType.NumField(); i++ {
// Check encoded field name
field := tsType.Field(i)
encodedValue, ok := encoded[field.Tag.Get(tag)]
if !ok {
t.Error("missing encoded value for field", field.Name)
continue
}
// Check encoded field value (against original value post-JSON enc + dec)
jsonName, ok := field.Tag.Lookup("json")
if !ok {
jsonName = field.Name
}
refValue := ref[jsonName]
if !reflect.DeepEqual(refValue, encodedValue) {
t.Error(fmt.Sprintf("incorrect encoded value for field %s. reference: %v, encoded: %v",
field.Name, refValue, encodedValue))
}
}
}
47 changes: 47 additions & 0 deletions _generated/omitempty.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,50 @@ type NotOmitEmpty10 struct {
Field08 string `msg:"field08"`
Field09 string `msg:"field09"`
}

type OmitEmptyNoName struct {
ABool bool `msg:",omitempty"`
AInt int `msg:",omitempty"`
AInt8 int8 `msg:",omitempty"`
AInt16 int16 `msg:",omitempty"`
AInt32 int32 `msg:",omitempty"`
AInt64 int64 `msg:",omitempty"`
AUint uint `msg:",omitempty"`
AUint8 uint8 `msg:",omitempty"`
AUint16 uint16 `msg:",omitempty"`
AUint32 uint32 `msg:",omitempty"`
AUint64 uint64 `msg:",omitempty"`
AFloat32 float32 `msg:",omitempty"`
AFloat64 float64 `msg:",omitempty"`
AComplex64 complex64 `msg:",omitempty"`
AComplex128 complex128 `msg:",omitempty"`

ANamedBool bool `msg:",omitempty"`
ANamedInt int `msg:",omitempty"`
ANamedFloat64 float64 `msg:",omitempty"`

AMapStrStr map[string]string `msg:",omitempty"`

APtrNamedStr *NamedString `msg:",omitempty"`

AString string `msg:",omitempty"`
AByteSlice []byte `msg:",omitempty"`

ASliceString []string `msg:",omitempty"`
ASliceNamedString []NamedString `msg:",omitempty"`

ANamedStruct NamedStruct `msg:",omitempty"`
APtrNamedStruct *NamedStruct `msg:",omitempty"`

AUnnamedStruct struct {
A string `msg:",omitempty"`
} `msg:",omitempty"` // omitempty not supported on unnamed struct

EmbeddableStruct `msg:",flatten,omitempty"` // embed flat

EmbeddableStruct2 `msg:",omitempty"` // embed non-flat

AArrayInt [5]int `msg:",omitempty"` // not supported

ATime time.Time `msg:",omitempty"`
}
75 changes: 70 additions & 5 deletions _generated/omitempty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package _generated

import (
"bytes"
"io/ioutil"
"io"
"testing"

"github.com/tinylib/msgp/msgp"
Expand Down Expand Up @@ -93,6 +93,71 @@ func TestOmitEmpty0(t *testing.T) {
}
}

func TestOmitEmptyNoNames(t *testing.T) {
var s string

var oe0a OmitEmptyNoName

s = mustEncodeToJSON(&oe0a)
if s != `{"AUnnamedStruct":{},"AArrayInt":[0,0,0,0,0]}` {
t.Errorf("wrong result: %s", s)
}

var oe0b OmitEmptyNoName
oe0b.AString = "teststr"
s = mustEncodeToJSON(&oe0b)
if s != `{"AString":"teststr","AUnnamedStruct":{},"AArrayInt":[0,0,0,0,0]}` {
t.Errorf("wrong result: %s", s)
}

// more than 15 fields filled in
var oe0c OmitEmptyNoName
oe0c.ABool = true
oe0c.AInt = 1
oe0c.AInt8 = 1
oe0c.AInt16 = 1
oe0c.AInt32 = 1
oe0c.AInt64 = 1
oe0c.AUint = 1
oe0c.AUint8 = 1
oe0c.AUint16 = 1
oe0c.AUint32 = 1
oe0c.AUint64 = 1
oe0c.AFloat32 = 1
oe0c.AFloat64 = 1
oe0c.AComplex64 = complex(1, 1)
oe0c.AComplex128 = complex(1, 1)
oe0c.AString = "test"
oe0c.ANamedBool = true
oe0c.ANamedInt = 1
oe0c.ANamedFloat64 = 1

var buf bytes.Buffer
en := msgp.NewWriter(&buf)
err := oe0c.EncodeMsg(en)
if err != nil {
t.Fatal(err)
}
en.Flush()
de := msgp.NewReader(&buf)
var oe0d OmitEmptyNoName
err = oe0d.DecodeMsg(de)
if err != nil {
t.Fatal(err)
}

// spot check some fields
if oe0c.AFloat32 != oe0d.AFloat32 {
t.Fail()
}
if oe0c.ANamedBool != oe0d.ANamedBool {
t.Fail()
}
if oe0c.AInt64 != oe0d.AInt64 {
t.Fail()
}
}

// TestOmitEmptyHalfFull tests mixed omitempty and not
func TestOmitEmptyHalfFull(t *testing.T) {
var s string
Expand Down Expand Up @@ -146,7 +211,7 @@ func TestOmitEmptyLotsOFields(t *testing.T) {
}

func BenchmarkOmitEmpty10AllEmpty(b *testing.B) {
en := msgp.NewWriter(ioutil.Discard)
en := msgp.NewWriter(io.Discard)
var s OmitEmpty10

b.ResetTimer()
Expand All @@ -160,7 +225,7 @@ func BenchmarkOmitEmpty10AllEmpty(b *testing.B) {
}

func BenchmarkOmitEmpty10AllFull(b *testing.B) {
en := msgp.NewWriter(ioutil.Discard)
en := msgp.NewWriter(io.Discard)
var s OmitEmpty10
s.Field00 = "this is the value of field00"
s.Field01 = "this is the value of field01"
Expand All @@ -184,7 +249,7 @@ func BenchmarkOmitEmpty10AllFull(b *testing.B) {
}

func BenchmarkNotOmitEmpty10AllEmpty(b *testing.B) {
en := msgp.NewWriter(ioutil.Discard)
en := msgp.NewWriter(io.Discard)
var s NotOmitEmpty10

b.ResetTimer()
Expand All @@ -198,7 +263,7 @@ func BenchmarkNotOmitEmpty10AllEmpty(b *testing.B) {
}

func BenchmarkNotOmitEmpty10AllFull(b *testing.B) {
en := msgp.NewWriter(ioutil.Discard)
en := msgp.NewWriter(io.Discard)
var s NotOmitEmpty10
s.Field00 = "this is the value of field00"
s.Field01 = "this is the value of field01"
Expand Down
11 changes: 4 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
module github.com/tinylib/msgp

go 1.18
go 1.20

require (
github.com/philhofer/fwd v1.1.2
golang.org/x/tools v0.14.0
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986
golang.org/x/tools v0.22.0
)

require (
golang.org/x/mod v0.13.0 // indirect
golang.org/x/sys v0.13.0 // indirect
)
require golang.org/x/mod v0.18.0 // indirect
15 changes: 7 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4=
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
15 changes: 5 additions & 10 deletions issue185_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"os"
"path/filepath"
"reflect"
Expand Down Expand Up @@ -39,15 +38,15 @@ func TestIssue185Idents(t *testing.T) {
for idx, identCase := range identCases {
// generate the code, extract the generated variable names, mapped to function name
var tplData issue185TplData
varsBefore, err := loadVars(identCase.tpl, tplData)
varsBefore, err := loadVars(t, identCase.tpl, tplData)
if err != nil {
t.Fatalf("%d: could not extract before vars: %v", idx, err)
}

// regenerate the code with extra field(s), extract the generated variable
// names, mapped to function name
tplData.Extra = true
varsAfter, err := loadVars(identCase.tpl, tplData)
varsAfter, err := loadVars(t, identCase.tpl, tplData)
if err != nil {
t.Fatalf("%d: could not extract after vars: %v", idx, err)
}
Expand Down Expand Up @@ -102,7 +101,7 @@ func TestIssue185Overlap(t *testing.T) {
for idx, o := range overlapCases {
// regenerate the code with extra field(s), extract the generated variable
// names, mapped to function name
mvars, err := loadVars(o.tpl, o.data)
mvars, err := loadVars(t, o.tpl, o.data)
if err != nil {
t.Fatalf("%d: could not extract after vars: %v", idx, err)
}
Expand Down Expand Up @@ -134,12 +133,8 @@ func TestIssue185Overlap(t *testing.T) {
}
}

func loadVars(tpl *template.Template, tplData interface{}) (vars extractedVars, err error) {
tempDir, err := ioutil.TempDir("", "msgp-")
if err != nil {
err = fmt.Errorf("could not create temp dir: %v", err)
return
}
func loadVars(t *testing.T, tpl *template.Template, tplData interface{}) (vars extractedVars, err error) {
tempDir := t.TempDir()

if !debugTemp {
defer os.RemoveAll(tempDir)
Expand Down
Loading

0 comments on commit f1e5a30

Please sign in to comment.