Skip to content

Commit

Permalink
Merge branch 'main' into enforce-new-auth
Browse files Browse the repository at this point in the history
  • Loading branch information
chilagrow committed Feb 15, 2024
2 parents 3699034 + e1eaaad commit 8e65773
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 51 deletions.
22 changes: 22 additions & 0 deletions internal/bson2/bson2.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ type (
// Null represents BSON scalar value null.
var Null = bsonproto.Null

//go:generate ../../bin/stringer -linecomment -type decodeMode

// decodeMode represents a mode for decoding BSON.
type decodeMode int

const (
_ decodeMode = iota

// DecodeShallow represents a mode in which only top-level fields/elements are decoded;
// nested documents and arrays are converted to RawDocument and RawArray respectively,
// using raw's subslices without copying.
decodeShallow

// DecodeDeep represents a mode in which nested documents and arrays are decoded recursively;
// RawDocuments and RawArrays are never returned.
decodeDeep

// DecodeCheckOnly represents a mode in which only validity checks are performed (recursively)
// and no decoding happens.
decodeCheckOnly
)

var (
// ErrDecodeShortInput is returned wrapped by Decode functions if the input bytes slice is too short.
ErrDecodeShortInput = bsonproto.ErrDecodeShortInput
Expand Down
26 changes: 26 additions & 0 deletions internal/bson2/decodemode_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

243 changes: 223 additions & 20 deletions internal/bson2/document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/FerretDB/FerretDB/internal/bson"
"github.com/FerretDB/FerretDB/internal/types"
"github.com/FerretDB/FerretDB/internal/util/debugbuild"
"github.com/FerretDB/FerretDB/internal/util/must"
"github.com/FerretDB/FerretDB/internal/util/testutil"
)
Expand Down Expand Up @@ -489,22 +490,198 @@ func TestDocument(t *testing.T) {
})

t.Run("bson2", func(t *testing.T) {
doc, err := RawDocument(tc.raw).DecodeDeep()
raw := RawDocument(tc.raw)

t.Run("Check", func(t *testing.T) {
err := raw.Check()

if tc.decodeErr != nil {
require.Error(t, err, "b:\n\n%s\n%#v", hex.Dump(tc.raw), tc.raw)
require.ErrorIs(t, err, tc.decodeErr)

return
}

require.NoError(t, err)
})

t.Run("Decode", func(t *testing.T) {
doc, err := raw.Decode()

if tc.decodeErr != nil {
if debugbuild.Enabled {
require.Error(t, err, "b:\n\n%s\n%#v", hex.Dump(tc.raw), tc.raw)
require.ErrorIs(t, err, tc.decodeErr)
}

return
}

require.NoError(t, err)

actual, err := doc.Convert()
require.NoError(t, err)
testutil.AssertEqual(t, tc.doc, actual)
})

t.Run("DecodeDeep", func(t *testing.T) {
doc, err := raw.DecodeDeep()

if tc.decodeErr != nil {
require.Error(t, err, "b:\n\n%s\n%#v", hex.Dump(tc.raw), tc.raw)
require.ErrorIs(t, err, tc.decodeErr)

return
}

require.NoError(t, err)

actual, err := doc.Convert()
require.NoError(t, err)
testutil.AssertEqual(t, tc.doc, actual)

ls := doc.LogValue().Resolve().String()
assert.NotContains(t, ls, "panicked")
assert.NotContains(t, ls, "called too many times")
})
})
})
})
}
}

func BenchmarkDocument(b *testing.B) {
b.Logf("debugbuild=%t", debugbuild.Enabled)

for _, tc := range documentTestCases {
tc := tc

b.Run(tc.name, func(b *testing.B) {
b.Run("Encode", func(b *testing.B) {
if tc.doc == nil {
b.Skip()
}

b.Run("bson", func(b *testing.B) {
doc, err := bson.ConvertDocument(tc.doc)
require.NoError(b, err)

var actual []byte

b.ResetTimer()

for i := 0; i < b.N; i++ {
actual, err = doc.MarshalBinary()
}

b.StopTimer()

require.NoError(b, err)
assert.NotNil(b, actual)
})

b.Run("bson2", func(b *testing.B) {
doc, err := ConvertDocument(tc.doc)
require.NoError(b, err)

var actual []byte

b.ResetTimer()

for i := 0; i < b.N; i++ {
actual, err = doc.Encode()
}

b.StopTimer()

require.NoError(b, err)
assert.NotNil(b, actual)
})
})

b.Run("Decode", func(b *testing.B) {
b.Run("bson/ReadFrom", func(b *testing.B) {
var doc bson.Document
var buf *bufio.Reader
var err error
br := bytes.NewReader(tc.raw)

b.ResetTimer()

for i := 0; i < b.N; i++ {
_, _ = br.Seek(0, io.SeekStart)
buf = bufio.NewReader(br)
err = doc.ReadFrom(buf)
}

b.StopTimer()

if tc.decodeErr != nil {
require.Error(t, err, "b:\n\n%s\n%#v", hex.Dump(tc.raw), tc.raw)
require.ErrorIs(t, err, tc.decodeErr)
require.Error(b, err)
return
}
require.NoError(t, err)

actual, err := doc.Convert()
require.NoError(t, err)
testutil.AssertEqual(t, tc.doc, actual)
require.NoError(b, err)
})

ls := doc.LogValue().Resolve().String()
assert.NotContains(t, ls, "panicked")
assert.NotContains(t, ls, "called too many times")
b.Run("bson2", func(b *testing.B) {
raw := RawDocument(tc.raw)

var doc *Document
var err error

b.Run("Check", func(b *testing.B) {
for i := 0; i < b.N; i++ {
err = raw.Check()
}

b.StopTimer()

if tc.decodeErr != nil {
require.Error(b, err)
return
}

require.NoError(b, err)
})

b.Run("Decode", func(b *testing.B) {
for i := 0; i < b.N; i++ {
doc, err = raw.Decode()
}

b.StopTimer()

if tc.decodeErr != nil {
if debugbuild.Enabled {
require.Error(b, err)
require.Nil(b, doc)
}

return
}

require.NoError(b, err)
require.NotNil(b, doc)
})

b.Run("DecodeDeep", func(b *testing.B) {
for i := 0; i < b.N; i++ {
doc, err = raw.DecodeDeep()
}

b.StopTimer()

if tc.decodeErr != nil {
require.Error(b, err)
require.Nil(b, doc)

return
}

require.NoError(b, err)
require.NotNil(b, doc)
})
})
})
})
Expand All @@ -524,18 +701,41 @@ func FuzzDocument(f *testing.F) {
t.Run("bson2", func(t *testing.T) {
t.Parallel()

doc, err := raw.DecodeDeep()
if err != nil {
t.Skip()
}
t.Run("Check", func(t *testing.T) {
t.Parallel()

actual, err := doc.Encode()
require.NoError(t, err)
assert.Equal(t, raw, actual, "actual:\n%s", hex.Dump(actual))
_ = raw.Check()
})

ls := doc.LogValue().Resolve().String()
assert.NotContains(t, ls, "panicked")
assert.NotContains(t, ls, "called too many times")
t.Run("Decode", func(t *testing.T) {
t.Parallel()

doc, err := raw.Decode()
if err != nil {
t.Skip()
}

actual, err := doc.Encode()
require.NoError(t, err)
assert.Equal(t, raw, actual, "actual:\n%s", hex.Dump(actual))
})

t.Run("DecodeDeep", func(t *testing.T) {
t.Parallel()

doc, err := raw.DecodeDeep()
if err != nil {
t.Skip()
}

actual, err := doc.Encode()
require.NoError(t, err)
assert.Equal(t, raw, actual, "actual:\n%s", hex.Dump(actual))

ls := doc.LogValue().Resolve().String()
assert.NotContains(t, ls, "panicked")
assert.NotContains(t, ls, "called too many times")
})
})

t.Run("cross", func(t *testing.T) {
Expand All @@ -558,6 +758,9 @@ func FuzzDocument(f *testing.F) {

// decode

checkErr := RawDocument(cb).Check()
require.NoError(t, checkErr)

bdoc2, err2 := RawDocument(cb).DecodeDeep()
require.NoError(t, err2)

Expand Down
Loading

0 comments on commit 8e65773

Please sign in to comment.