diff --git a/go.mod b/go.mod index 49d398e..4b93a2a 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/FerretDB/wire -go 1.22 +go 1.23 -toolchain go1.22.6 +toolchain go1.23.1 require ( github.com/stretchr/testify v1.9.0 diff --git a/msg_body.go b/msg_body.go index c81ef65..cb02180 100644 --- a/msg_body.go +++ b/msg_body.go @@ -37,11 +37,8 @@ type MsgBody interface { fmt.Stringer - // StringBlock returns an indented string representation for logging. - StringBlock() string - - // StringFlow returns an unindented string representation for logging. - StringFlow() string + // StringIndent returns an indented string representation for logging. + StringIndent() string // check performs deep (and slow) validity check. check() error diff --git a/op_msg.go b/op_msg.go index 63b8f2f..4f17074 100644 --- a/op_msg.go +++ b/op_msg.go @@ -367,19 +367,14 @@ func (msg *OpMsg) logMessage(logFunc func(v any) string) string { return logFunc(m) } -// String returns a string representation for logging. +// String returns an string representation for logging. func (msg *OpMsg) String() string { return msg.logMessage(wirebson.LogMessage) } -// StringBlock returns an indented string representation for logging. -func (msg *OpMsg) StringBlock() string { - return msg.logMessage(wirebson.LogMessageBlock) -} - -// StringFlow returns an unindented string representation for logging. -func (msg *OpMsg) StringFlow() string { - return msg.logMessage(wirebson.LogMessageFlow) +// StringIndent returns an indented string representation for logging. +func (msg *OpMsg) StringIndent() string { + return msg.logMessage(wirebson.LogMessageIndent) } // check interfaces diff --git a/op_msg_test.go b/op_msg_test.go index 94056db..6fbe480 100644 --- a/op_msg_test.go +++ b/op_msg_test.go @@ -53,7 +53,7 @@ var msgTestCases = []testCase{ }}, }, command: "buildInfo", - m: ` + b: ` { "FlagBits": "[]", "Checksum": int64(0), @@ -62,7 +62,9 @@ var msgTestCases = []testCase{ "Kind": 0, "Document": { "buildInfo": 1, - "lsid": {"id": Binary(uuid:oxnytKF1QMe456OjLsJWvg==)}, + "lsid": { + "id": Binary(uuid:oxnytKF1QMe456OjLsJWvg==), + }, "$db": "admin", }, }, @@ -126,7 +128,7 @@ var msgTestCases = []testCase{ }}, }, command: "version", - m: ` + b: ` { "FlagBits": "[]", "Checksum": int64(0), @@ -140,7 +142,12 @@ var msgTestCases = []testCase{ "allocator": "tcmalloc", "javascriptEngine": "mozjs", "sysInfo": "deprecated", - "versionArray": [5, 0, 0, 0], + "versionArray": [ + 5, + 0, + 0, + 0, + ], "openssl": { "running": "OpenSSL 1.1.1f 31 Mar 2020", "compiled": "OpenSSL 1.1.1f 31 Mar 2020", @@ -160,7 +167,11 @@ var msgTestCases = []testCase{ "bits": 64, "debug": false, "maxBsonObjectSize": 16777216, - "storageEngines": ["devnull", "ephemeralForTest", "wiredTiger"], + "storageEngines": [ + "devnull", + "ephemeralForTest", + "wiredTiger", + ], "ok": 1.0, }, }, @@ -210,7 +221,7 @@ var msgTestCases = []testCase{ }, }, command: "insert", - m: ` + b: ` { "FlagBits": "[]", "Checksum": int64(0), @@ -220,7 +231,9 @@ var msgTestCases = []testCase{ "Document": { "insert": "actor", "ordered": true, - "writeConcern": {"w": "majority"}, + "writeConcern": { + "w": "majority", + }, "$db": "monila", }, }, @@ -302,7 +315,7 @@ var msgTestCases = []testCase{ }}, }, command: "insert", - m: ` + b: ` { "FlagBits": "[]", "Checksum": int64(0), @@ -311,7 +324,12 @@ var msgTestCases = []testCase{ "Kind": 0, "Document": { "insert": "values", - "documents": [{"v": NaN, "_id": ObjectID(6377f213757c0babdebc2f6a)}], + "documents": [ + { + "v": NaN, + "_id": ObjectID(6377f213757c0babdebc2f6a), + }, + ], "ordered": true, "$db": "test", }, @@ -371,19 +389,28 @@ var msgTestCases = []testCase{ }, }, command: "insert", - m: ` + b: ` { "FlagBits": "[]", "Checksum": int64(0), "Sections": [ { "Kind": 0, - "Document": {"insert": "TestInsertSimple", "ordered": true, "$db": "testinsertsimple"}, + "Document": { + "insert": "TestInsertSimple", + "ordered": true, + "$db": "testinsertsimple", + }, }, { "Kind": 1, "Identifier": "documents", - "Documents": [{"_id": ObjectID(637cfad88dc3cecde38e1e6b), "v": -0.0}], + "Documents": [ + { + "_id": ObjectID(637cfad88dc3cecde38e1e6b), + "v": -0.0, + }, + ], }, ], }`, @@ -448,7 +475,7 @@ var msgTestCases = []testCase{ checksum: 1737537506, }, command: "insert", - m: ` + b: ` { "FlagBits": "[checksumPresent]", "Checksum": int64(1737537506), @@ -456,9 +483,21 @@ var msgTestCases = []testCase{ { "Kind": 1, "Identifier": "documents", - "Documents": [{"_id": ObjectID(638cec46aa778bf370105429), "a": 3.0}], + "Documents": [ + { + "_id": ObjectID(638cec46aa778bf370105429), + "a": 3.0, + }, + ], + }, + { + "Kind": 0, + "Document": { + "insert": "foo", + "ordered": true, + "$db": "test", + }, }, - {"Kind": 0, "Document": {"insert": "foo", "ordered": true, "$db": "test"}}, ], }`, }, @@ -545,7 +584,7 @@ var msgTestCases = []testCase{ checksum: 2932997361, }, command: "update", - m: ` + b: ` { "FlagBits": "[checksumPresent]", "Checksum": int64(2932997361), @@ -554,10 +593,28 @@ var msgTestCases = []testCase{ "Kind": 1, "Identifier": "updates", "Documents": [ - {"q": {"a": 20.0}, "u": {"$inc": {"a": 1.0}}, "multi": false, "upsert": false}, + { + "q": { + "a": 20.0, + }, + "u": { + "$inc": { + "a": 1.0, + }, + }, + "multi": false, + "upsert": false, + }, ], }, - {"Kind": 0, "Document": {"update": "foo", "ordered": true, "$db": "test"}}, + { + "Kind": 0, + "Document": { + "update": "foo", + "ordered": true, + "$db": "test", + }, + }, ], }`, }, diff --git a/op_query.go b/op_query.go index 64ad89b..36cc71b 100644 --- a/op_query.go +++ b/op_query.go @@ -188,19 +188,14 @@ func (query *OpQuery) logMessage(logFunc func(v any) string) string { return logFunc(m) } -// String returns a string representation for logging. +// String returns an string representation for logging. func (query *OpQuery) String() string { return query.logMessage(wirebson.LogMessage) } -// StringBlock returns an indented string representation for logging. -func (query *OpQuery) StringBlock() string { - return query.logMessage(wirebson.LogMessageBlock) -} - -// StringFlow returns an unindented string representation for logging. -func (query *OpQuery) StringFlow() string { - return query.logMessage(wirebson.LogMessageFlow) +// StringIndent returns an indented string representation for logging. +func (query *OpQuery) StringIndent() string { + return query.logMessage(wirebson.LogMessageIndent) } // check interfaces diff --git a/op_query_test.go b/op_query_test.go index 4ba7e5a..96818a4 100644 --- a/op_query_test.go +++ b/op_query_test.go @@ -60,7 +60,7 @@ var queryTestCases = []testCase{ ), returnFieldsSelector: nil, }, - m: ` + b: ` { "Flags": "[]", "FullCollectionName": "admin.$cmd", @@ -69,7 +69,10 @@ var queryTestCases = []testCase{ "Query": { "ismaster": true, "client": { - "driver": {"name": "nodejs", "version": "4.0.0-beta.6"}, + "driver": { + "name": "nodejs", + "version": "4.0.0-beta.6", + }, "os": { "type": "Darwin", "name": "darwin", @@ -77,9 +80,13 @@ var queryTestCases = []testCase{ "version": "20.6.0", }, "platform": "Node.js v14.17.3, LE (unified)|Node.js v14.17.3, LE (unified)", - "application": {"name": "mongosh 1.0.1"}, + "application": { + "name": "mongosh 1.0.1", + }, }, - "compression": ["none"], + "compression": [ + "none", + ], "loadBalanced": false, }, }`, @@ -122,7 +129,7 @@ var queryTestCases = []testCase{ ), returnFieldsSelector: nil, }, - m: ` + b: ` { "Flags": "[]", "FullCollectionName": "admin.$cmd", @@ -131,7 +138,10 @@ var queryTestCases = []testCase{ "Query": { "ismaster": true, "client": { - "driver": {"name": "nodejs", "version": "4.0.0-beta.6"}, + "driver": { + "name": "nodejs", + "version": "4.0.0-beta.6", + }, "os": { "type": "Darwin", "name": "darwin", @@ -139,9 +149,13 @@ var queryTestCases = []testCase{ "version": "20.6.0", }, "platform": "Node.js v14.17.3, LE (unified)|Node.js v14.17.3, LE (unified)", - "application": {"name": "mongosh 1.0.1"}, + "application": { + "name": "mongosh 1.0.1", + }, }, - "compression": ["none"], + "compression": [ + "none", + ], "loadBalanced": false, }, }`, diff --git a/op_reply.go b/op_reply.go index 6056fab..b75d8be 100644 --- a/op_reply.go +++ b/op_reply.go @@ -166,19 +166,14 @@ func (reply *OpReply) logMessage(logFunc func(v any) string) string { return logFunc(m) } -// String returns a string representation for logging. +// String returns an string representation for logging. func (reply *OpReply) String() string { return reply.logMessage(wirebson.LogMessage) } -// StringBlock returns an indented string representation for logging. -func (reply *OpReply) StringBlock() string { - return reply.logMessage(wirebson.LogMessageBlock) -} - -// StringFlow returns an unindented string representation for logging. -func (reply *OpReply) StringFlow() string { - return reply.logMessage(wirebson.LogMessageFlow) +// StringIndent returns an indented string representation for logging. +func (reply *OpReply) StringIndent() string { + return reply.logMessage(wirebson.LogMessageIndent) } // check interfaces diff --git a/op_reply_test.go b/op_reply_test.go index 5ea9657..05c2db4 100644 --- a/op_reply_test.go +++ b/op_reply_test.go @@ -55,7 +55,7 @@ var replyTestCases = []testCase{ "ok", float64(1), ), }, - m: ` + b: ` { "ResponseFlags": "[AwaitCapable]", "CursorID": int64(0), @@ -63,7 +63,10 @@ var replyTestCases = []testCase{ "NumberReturned": 1, "Document": { "ismaster": true, - "topologyVersion": {"processId": ObjectID(60fbed5371fe1bae70339505), "counter": int64(0)}, + "topologyVersion": { + "processId": ObjectID(60fbed5371fe1bae70339505), + "counter": int64(0), + }, "maxBsonObjectSize": 16777216, "maxMessageSizeBytes": 48000000, "maxWriteBatchSize": 100000, @@ -109,7 +112,7 @@ var replyTestCases = []testCase{ "ok", float64(1), ), }, - m: ` + b: ` { "ResponseFlags": "[AwaitCapable]", "CursorID": int64(0), @@ -117,7 +120,10 @@ var replyTestCases = []testCase{ "NumberReturned": 1, "Document": { "ismaster": true, - "topologyVersion": {"processId": ObjectID(60fbed5371fe1bae70339505), "counter": int64(0)}, + "topologyVersion": { + "processId": ObjectID(60fbed5371fe1bae70339505), + "counter": int64(0), + }, "maxBsonObjectSize": 16777216, "maxMessageSizeBytes": 48000000, "maxWriteBatchSize": 100000, diff --git a/tools/go.mod b/tools/go.mod index 9d08ab0..4fa0bee 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,8 +1,8 @@ module github.com/FerretDB/wire/tools -go 1.22.1 +go 1.23 -toolchain go1.22.6 +toolchain go1.23.1 require ( github.com/go-task/task/v3 v3.38.0 diff --git a/wire_test.go b/wire_test.go index 533a192..94ce005 100644 --- a/wire_test.go +++ b/wire_test.go @@ -70,7 +70,7 @@ type testCase struct { msgHeader *MsgHeader msgBody MsgBody command string // only for OpMsg - m string + b string err string // unwrapped } @@ -127,9 +127,8 @@ func testMessages(t *testing.T, testCases []testCase) { require.NotNil(t, msgHeader) require.NotNil(t, msgBody) assert.NotEmpty(t, msgHeader.String()) - assert.Equal(t, testutil.Unindent(tc.m), msgBody.String()) - assert.NotEmpty(t, msgBody.StringBlock()) - assert.NotEmpty(t, msgBody.StringFlow()) + assert.Equal(t, testutil.Unindent(tc.b), msgBody.StringIndent()) + assert.NotEmpty(t, msgBody.String()) require.NoError(t, msgBody.check()) @@ -218,9 +217,8 @@ func fuzzMessages(f *testing.F, testCases []testCase) { if msgBody.check() != nil { assert.NotEmpty(t, msgHeader.String()) + assert.NotEmpty(t, msgBody.StringIndent()) assert.NotEmpty(t, msgBody.String()) - assert.NotEmpty(t, msgBody.StringBlock()) - assert.NotEmpty(t, msgBody.StringFlow()) if msg, ok := msgBody.(*OpMsg); ok { assert.NotPanics(t, func() { diff --git a/wirebson/array_iter.go b/wirebson/array_iter.go index f129d45..803a0c1 100644 --- a/wirebson/array_iter.go +++ b/wirebson/array_iter.go @@ -12,11 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// We should remove the build tag below once we use 1.23 everywhere. -// TODO https://github.com/FerretDB/wire/issues/9 - -//go:build go1.23 - package wirebson import ( diff --git a/wirebson/bson_iter_test.go b/wirebson/bson_iter_test.go index 9e64038..6205f36 100644 --- a/wirebson/bson_iter_test.go +++ b/wirebson/bson_iter_test.go @@ -12,11 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// We should remove the build tag below once we use 1.23 everywhere. -// TODO https://github.com/FerretDB/wire/issues/9 - -//go:build go1.23 - package wirebson import ( diff --git a/wirebson/bson_test.go b/wirebson/bson_test.go index 0da80a4..37ea2b6 100644 --- a/wirebson/bson_test.go +++ b/wirebson/bson_test.go @@ -31,7 +31,7 @@ type normalTestCase struct { name string raw RawDocument doc *Document - m string + b string } // decodeTestCase represents a single test case for unsuccessful decoding. @@ -77,11 +77,14 @@ var normalTestCases = []normalTestCase{ "compression", MustArray("none"), "loadBalanced", false, ), - m: ` + b: ` { "ismaster": true, "client": { - "driver": {"name": "nodejs", "version": "4.0.0-beta.6"}, + "driver": { + "name": "nodejs", + "version": "4.0.0-beta.6", + }, "os": { "type": "Darwin", "name": "darwin", @@ -89,9 +92,13 @@ var normalTestCases = []normalTestCase{ "version": "20.6.0", }, "platform": "Node.js v14.17.3, LE (unified)|Node.js v14.17.3, LE (unified)", - "application": {"name": "mongosh 1.0.1"}, + "application": { + "name": "mongosh 1.0.1", + }, }, - "compression": ["none"], + "compression": [ + "none", + ], "loadBalanced": false, }`, }, @@ -119,11 +126,14 @@ var normalTestCases = []normalTestCase{ "compression", MustArray("none"), "loadBalanced", false, ), - m: ` + b: ` { "ismaster": true, "client": { - "driver": {"name": "nodejs", "version": "4.0.0-beta.6"}, + "driver": { + "name": "nodejs", + "version": "4.0.0-beta.6", + }, "os": { "type": "Darwin", "name": "darwin", @@ -131,9 +141,13 @@ var normalTestCases = []normalTestCase{ "version": "20.6.0", }, "platform": "Node.js v14.17.3, LE (unified)|Node.js v14.17.3, LE (unified)", - "application": {"name": "mongosh 1.0.1"}, + "application": { + "name": "mongosh 1.0.1", + }, }, - "compression": ["none"], + "compression": [ + "none", + ], "loadBalanced": false, }`, }, @@ -153,10 +167,12 @@ var normalTestCases = []normalTestCase{ ), "$db", "admin", ), - m: ` + b: ` { "buildInfo": 1, - "lsid": {"id": Binary(uuid:oxnytKF1QMe456OjLsJWvg==)}, + "lsid": { + "id": Binary(uuid:oxnytKF1QMe456OjLsJWvg==), + }, "$db": "admin", }`, }, @@ -204,7 +220,7 @@ var normalTestCases = []normalTestCase{ "storageEngines", MustArray("devnull", "ephemeralForTest", "wiredTiger"), "ok", float64(1), ), - m: ` + b: ` { "version": "5.0.0", "gitVersion": "1184f004a99660de6f5e745573419bda8a28c0e9", @@ -212,7 +228,12 @@ var normalTestCases = []normalTestCase{ "allocator": "tcmalloc", "javascriptEngine": "mozjs", "sysInfo": "deprecated", - "versionArray": [5, 0, 0, 0], + "versionArray": [ + 5, + 0, + 0, + 0, + ], "openssl": { "running": "OpenSSL 1.1.1f 31 Mar 2020", "compiled": "OpenSSL 1.1.1f 31 Mar 2020", @@ -232,7 +253,11 @@ var normalTestCases = []normalTestCase{ "bits": 64, "debug": false, "maxBsonObjectSize": 16777216, - "storageEngines": ["devnull", "ephemeralForTest", "wiredTiger"], + "storageEngines": [ + "devnull", + "ephemeralForTest", + "wiredTiger", + ], "ok": 1.0, }`, }, @@ -265,31 +290,108 @@ var normalTestCases = []normalTestCase{ "timestamp", MustArray(Timestamp(42), Timestamp(0)), "decimal128", MustArray(Decimal128{L: 42, H: 13}), ), - m: ` + b: ` { - "array": [[""], ["foo"]], - "binary": [Binary(user:Qg==), Binary(generic:)], - "bool": [true, false], - "datetime": [2021-07-27T09:35:42.123Z, 0001-01-01T00:00:00Z], - "document": [{"foo": ""}, {"": "foo"}], - "double": [42.13, 0.0], - "int32": [42, 0], - "int64": [int64(42), int64(0)], - "objectID": [ObjectID(420000000000000000000000), ObjectID(000000000000000000000000)], - "string": ["foo", ""], - "timestamp": [Timestamp(42), Timestamp(0)], - "decimal128": [Decimal128(42,13)], + "array": [ + [ + "", + ], + [ + "foo", + ], + ], + "binary": [ + Binary(user:Qg==), + Binary(generic:), + ], + "bool": [ + true, + false, + ], + "datetime": [ + 2021-07-27T09:35:42.123Z, + 0001-01-01T00:00:00Z, + ], + "document": [ + { + "foo": "", + }, + { + "": "foo", + }, + ], + "double": [ + 42.13, + 0.0, + ], + "int32": [ + 42, + 0, + ], + "int64": [ + int64(42), + int64(0), + ], + "objectID": [ + ObjectID(420000000000000000000000), + ObjectID(000000000000000000000000), + ], + "string": [ + "foo", + "", + ], + "timestamp": [ + Timestamp(42), + Timestamp(0), + ], + "decimal128": [ + Decimal128(42,13), + ], }`, }, { name: "nested", raw: testutil.MustParseDumpFile("testdata", "nested.hex"), doc: makeNested(false, 150).(*Document), - m: ` + b: ` { "f": [ { - "f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{...}]}]}]}]}]}]}]}]}], + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + {...}, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], }, ], }`, @@ -305,7 +407,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", float64(3.141592653589793), ), - m: `{"f": 3.141592653589793}`, + b: ` + { + "f": 3.141592653589793, + }`, }, { name: "stringDoc", @@ -319,7 +424,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", "v", ), - m: `{"f": "v"}`, + b: ` + { + "f": "v", + }`, }, { name: "binaryDoc", @@ -334,7 +442,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", Binary{B: []byte("v"), Subtype: BinaryUser}, ), - m: `{"f": Binary(user:dg==)}`, + b: ` + { + "f": Binary(user:dg==), + }`, }, { name: "objectIDDoc", @@ -347,7 +458,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", ObjectID{0x62, 0x56, 0xc5, 0xba, 0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}, ), - m: `{"f": ObjectID(6256c5ba182d4454fb210940)}`, + b: ` + { + "f": ObjectID(6256c5ba182d4454fb210940), + }`, }, { name: "boolDoc", @@ -360,7 +474,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", true, ), - m: `{"f": true}`, + b: ` + { + "f": true, + }`, }, { name: "timeDoc", @@ -373,7 +490,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", time.Date(2024, 1, 17, 17, 40, 42, 123000000, time.UTC), ), - m: `{"f": 2024-01-17T17:40:42.123Z}`, + b: ` + { + "f": 2024-01-17T17:40:42.123Z, + }`, }, { name: "nullDoc", @@ -385,7 +505,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", Null, ), - m: `{"f": null}`, + b: ` + { + "f": null, + }`, }, { name: "regexDoc", @@ -399,7 +522,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", Regex{Pattern: "p", Options: "o"}, ), - m: `{"f": /p/o}`, + b: ` + { + "f": /p/o, + }`, }, { name: "int32Doc", @@ -412,7 +538,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", int32(314159265), ), - m: `{"f": 314159265}`, + b: ` + { + "f": 314159265, + }`, }, { name: "timestampDoc", @@ -425,7 +554,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", Timestamp(42), ), - m: `{"f": Timestamp(42)}`, + b: ` + { + "f": Timestamp(42), + }`, }, { name: "int64Doc", @@ -438,7 +570,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", int64(3141592653589793), ), - m: `{"f": int64(3141592653589793)}`, + b: ` + { + "f": int64(3141592653589793), + }`, }, { name: "decimal128Doc", @@ -451,7 +586,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "f", Decimal128{L: 42, H: 13}, ), - m: `{"f": Decimal128(42,13)}`, + b: ` + { + "f": Decimal128(42,13), + }`, }, { name: "smallDoc", @@ -464,7 +602,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "foo", MustDocument(), ), - m: `{"foo": {}}`, + b: ` + { + "foo": {}, + }`, }, { name: "smallArray", @@ -477,7 +618,10 @@ var normalTestCases = []normalTestCase{ doc: MustDocument( "foo", MustArray(), ), - m: `{"foo": []}`, + b: ` + { + "foo": [], + }`, }, { name: "duplicateKeys", @@ -491,7 +635,11 @@ var normalTestCases = []normalTestCase{ "", false, "", true, ), - m: `{"": false, "": true}`, + b: ` + { + "": false, + "": true, + }`, }, } @@ -601,8 +749,7 @@ func TestNormal(t *testing.T) { assert.NotContains(t, ls, "called too many times") assert.NotEmpty(t, LogMessage(tc.raw)) - assert.NotEmpty(t, LogMessageBlock(tc.raw)) - assert.NotEmpty(t, LogMessageFlow(tc.raw)) + assert.NotEmpty(t, LogMessageIndent(tc.raw)) l, err := FindRaw(tc.raw) require.NoError(t, err) @@ -618,8 +765,7 @@ func TestNormal(t *testing.T) { assert.NotContains(t, ls, "called too many times") assert.NotEmpty(t, LogMessage(doc)) - assert.NotEmpty(t, LogMessageBlock(doc)) - assert.NotEmpty(t, LogMessageFlow(doc)) + assert.NotEmpty(t, LogMessageIndent(doc)) raw, err := doc.Encode() require.NoError(t, err) @@ -634,9 +780,8 @@ func TestNormal(t *testing.T) { assert.NotContains(t, ls, "panicked") assert.NotContains(t, ls, "called too many times") - assert.Equal(t, testutil.Unindent(tc.m), LogMessage(doc)) - assert.NotEmpty(t, LogMessageBlock(doc)) - assert.NotEmpty(t, LogMessageFlow(doc)) + assert.NotEmpty(t, LogMessage(doc)) + assert.Equal(t, testutil.Unindent(tc.b), LogMessageIndent(doc)) raw, err := doc.Encode() require.NoError(t, err) @@ -661,8 +806,7 @@ func TestDecode(t *testing.T) { assert.NotContains(t, ls, "called too many times") assert.NotEmpty(t, LogMessage(tc.raw)) - assert.NotEmpty(t, LogMessageBlock(tc.raw)) - assert.NotEmpty(t, LogMessageFlow(tc.raw)) + assert.NotEmpty(t, LogMessageIndent(tc.raw)) l, err := FindRaw(tc.raw) @@ -750,6 +894,22 @@ func BenchmarkDocument(b *testing.B) { assert.NotContains(b, m, "called too many times") }) + b.Run("LogMessageIndent", func(b *testing.B) { + doc, err = tc.raw.Decode() + require.NoError(b, err) + + b.ReportAllocs() + b.ResetTimer() + + for range b.N { + m = LogMessageIndent(doc) + } + + b.StopTimer() + + assert.NotEmpty(b, m) + }) + b.Run("LogMessage", func(b *testing.B) { doc, err = tc.raw.Decode() require.NoError(b, err) @@ -814,6 +974,22 @@ func BenchmarkDocument(b *testing.B) { assert.NotContains(b, m, "called too many times") }) + b.Run("LogMessageIndentDeep", func(b *testing.B) { + doc, err = tc.raw.DecodeDeep() + require.NoError(b, err) + + b.ReportAllocs() + b.ResetTimer() + + for range b.N { + m = LogMessageIndent(doc) + } + + b.StopTimer() + + assert.NotEmpty(b, m) + }) + b.Run("LogMessageDeep", func(b *testing.B) { doc, err = tc.raw.DecodeDeep() require.NoError(b, err) @@ -844,8 +1020,7 @@ func testRawDocument(t *testing.T, rawDoc RawDocument) { assert.NotContains(t, ls, "called too many times") assert.NotEmpty(t, LogMessage(rawDoc)) - assert.NotEmpty(t, LogMessageBlock(rawDoc)) - assert.NotEmpty(t, LogMessageFlow(rawDoc)) + assert.NotEmpty(t, LogMessageIndent(rawDoc)) _, _ = FindRaw(rawDoc) }) @@ -864,8 +1039,7 @@ func testRawDocument(t *testing.T, rawDoc RawDocument) { assert.NotContains(t, ls, "called too many times") assert.NotEmpty(t, LogMessage(doc)) - assert.NotEmpty(t, LogMessageBlock(doc)) - assert.NotEmpty(t, LogMessageFlow(doc)) + assert.NotEmpty(t, LogMessageIndent(doc)) raw, err := doc.Encode() if err == nil { @@ -884,8 +1058,7 @@ func testRawDocument(t *testing.T, rawDoc RawDocument) { assert.NotContains(t, ls, "called too many times") assert.NotEmpty(t, LogMessage(doc)) - assert.NotEmpty(t, LogMessageBlock(doc)) - assert.NotEmpty(t, LogMessageFlow(doc)) + assert.NotEmpty(t, LogMessageIndent(doc)) raw, err := doc.Encode() require.NoError(t, err) diff --git a/wirebson/document.go b/wirebson/document.go index 9ca7746..10b0d38 100644 --- a/wirebson/document.go +++ b/wirebson/document.go @@ -119,7 +119,6 @@ func (doc *Document) FieldNames() []string { // If Document contains duplicate field names, it returns the first one. // To get other fields, a for/range loop can be used with [Document.Len] and [Document.GetByIndex]. // Or iterators. -// TODO https://github.com/FerretDB/wire/issues/9 func (doc *Document) Get(name string) any { for _, f := range doc.fields { if f.name == name { diff --git a/wirebson/document_iter.go b/wirebson/document_iter.go index ddc7e92..9b2211e 100644 --- a/wirebson/document_iter.go +++ b/wirebson/document_iter.go @@ -12,11 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// We should remove the build tag below once we use 1.23 everywhere. -// TODO https://github.com/FerretDB/wire/issues/9 - -//go:build go1.23 - package wirebson import ( diff --git a/wirebson/logging.go b/wirebson/logging.go index 195df9f..4e79392 100644 --- a/wirebson/logging.go +++ b/wirebson/logging.go @@ -28,10 +28,6 @@ import ( // logMaxDepth is the maximum depth of a recursive representation of a BSON value. const logMaxDepth = 20 -// logMaxFlowLength is the maximum length of a flow/inline/compact representation of a BSON value. -// It may be set to 0 to always disable flow representation. -const logMaxFlowLength = 80 - // nanBits is the most common pattern of a NaN float64 value, the same as math.Float64bits(math.NaN()). const nanBits = 0b111111111111000000000000000000000000000000000000000000000000001 @@ -149,17 +145,13 @@ func slogValue(v any, depth int) slog.Value { // LogMessage returns a representation as a string. // It may change over time. func LogMessage(v any) string { - return logMessage(v, logMaxFlowLength, "", 1) -} - -// LogMessageBlock is a variant of [LogMessage] that never uses a flow style. -func LogMessageBlock(v any) string { - return logMessage(v, 0, "", 1) + return logMessage(v, -1, 1) } -// LogMessageFlow is a variant of [LogMessage] that always uses a flow style. -func LogMessageFlow(v any) string { - return logMessage(v, math.MaxInt, "", 1) +// LogMessageIndent returns a representation as an indented string. +// It may change over time. +func LogMessageIndent(v any) string { + return logMessage(v, 0, 1) } // logMessage returns an indented representation of any BSON value as a string, @@ -170,7 +162,7 @@ func LogMessageFlow(v any) string { // All information is preserved. // // TODO https://github.com/FerretDB/wire/issues/23 -func logMessage(v any, maxFlowLength int, indent string, depth int) string { +func logMessage(v any, indent, depth int) string { switch v := v.(type) { case *Document: if v == nil { @@ -186,38 +178,32 @@ func logMessage(v any, maxFlowLength int, indent string, depth int) string { return "{...}" } - if maxFlowLength > 0 { + if indent < 0 { res := "{" for i, f := range v.fields { res += strconv.Quote(f.name) + `: ` - res += logMessage(f.value, maxFlowLength, "", depth+1) + res += logMessage(f.value, -1, depth+1) if i != l-1 { res += ", " } - - if len(res) >= maxFlowLength { - break - } } res += `}` - if len(res) < maxFlowLength { - return res - } + return res } res := "{\n" for _, f := range v.fields { - res += indent + " " + res += strings.Repeat(" ", indent+1) res += strconv.Quote(f.name) + `: ` - res += logMessage(f.value, maxFlowLength, indent+" ", depth+1) + ",\n" + res += logMessage(f.value, indent+1, depth+1) + ",\n" } - res += indent + `}` + res += strings.Repeat(" ", indent) + `}` return res @@ -238,36 +224,30 @@ func logMessage(v any, maxFlowLength int, indent string, depth int) string { return "[...]" } - if maxFlowLength > 0 { + if indent < 0 { res := "[" for i, e := range v.elements { - res += logMessage(e, maxFlowLength, "", depth+1) + res += logMessage(e, -1, depth+1) if i != l-1 { res += ", " } - - if len(res) >= maxFlowLength { - break - } } res += `]` - if len(res) < maxFlowLength { - return res - } + return res } res := "[\n" for _, e := range v.elements { - res += indent + " " - res += logMessage(e, maxFlowLength, indent+" ", depth+1) + ",\n" + res += strings.Repeat(" ", indent+1) + res += logMessage(e, indent+1, depth+1) + ",\n" } - res += indent + `]` + res += strings.Repeat(" ", indent) + `]` return res diff --git a/wirebson/logging_test.go b/wirebson/logging_test.go index 224b68c..570cce5 100644 --- a/wirebson/logging_test.go +++ b/wirebson/logging_test.go @@ -31,10 +31,12 @@ func TestLoggingNil(t *testing.T) { var doc *Document assert.Equal(t, doc.LogValue().String(), "Document") assert.Equal(t, LogMessage(doc), "{}") + assert.Equal(t, LogMessageIndent(doc), "{}") var arr *Array assert.Equal(t, arr.LogValue().String(), "Array") assert.Equal(t, LogMessage(arr), "[]") + assert.Equal(t, LogMessageIndent(arr), "[]") } func TestLogging(t *testing.T) { @@ -69,8 +71,8 @@ func TestLogging(t *testing.T) { doc any t string j string + mi string m string - b string }{ { name: "Numbers", @@ -81,23 +83,13 @@ func TestLogging(t *testing.T) { "zero", math.Copysign(0, 1), "neg_zero", math.Copysign(0, -1), "nan", float64(math.NaN()), + "nan_weird", float64(math.Float64frombits(0x7ff8000f000f0001)), "i32", int32(42), "i64", int64(42), ), - t: `v.f64=42 v.inf=+Inf v.neg_inf=-Inf v.zero=0 v.neg_zero=-0 v.nan=NaN v.i32=42 v.i64=42`, - j: `{"v":{"f64":42,"inf":"+Inf","neg_inf":"-Inf","zero":0,"neg_zero":-0,"nan":"NaN","i32":42,"i64":42}}`, - m: ` - { - "f64": 42.0, - "inf": +Inf, - "neg_inf": -Inf, - "zero": 0.0, - "neg_zero": -0.0, - "nan": NaN, - "i32": 42, - "i64": int64(42), - }`, - b: ` + t: `v.f64=42 v.inf=+Inf v.neg_inf=-Inf v.zero=0 v.neg_zero=-0 v.nan=NaN v.nan_weird=NaN v.i32=42 v.i64=42`, + j: `{"v":{"f64":42,"inf":"+Inf","neg_inf":"-Inf","zero":0,"neg_zero":-0,"nan":"NaN","nan_weird":"NaN","i32":42,"i64":42}}`, + mi: ` { "f64": 42.0, "inf": +Inf, @@ -105,9 +97,13 @@ func TestLogging(t *testing.T) { "zero": 0.0, "neg_zero": -0.0, "nan": NaN, + "nan_weird": NaN(111111111111000000000000000111100000000000011110000000000000001), "i32": 42, "i64": int64(42), }`, + m: `{"f64": 42.0, "inf": +Inf, "neg_inf": -Inf, "zero": 0.0, "neg_zero": -0.0, "nan": NaN, ` + + `"nan_weird": NaN(111111111111000000000000000111100000000000011110000000000000001), ` + + `"i32": 42, "i64": int64(42)}`, }, { name: "Scalars", @@ -119,20 +115,14 @@ func TestLogging(t *testing.T) { ), t: `v.null= v.id=ObjectID(420000000000000000000000) v.bool=true v.time=2023-03-06T09:14:42.123Z`, j: `{"v":{"null":null,"id":"ObjectID(420000000000000000000000)","bool":true,"time":"2023-03-06T09:14:42.123Z"}}`, - m: ` - { - "null": null, - "id": ObjectID(420000000000000000000000), - "bool": true, - "time": 2023-03-06T09:14:42.123Z, - }`, - b: ` + mi: ` { "null": null, "id": ObjectID(420000000000000000000000), "bool": true, "time": 2023-03-06T09:14:42.123Z, }`, + m: `{"null": null, "id": ObjectID(420000000000000000000000), "bool": true, "time": 2023-03-06T09:14:42.123Z}`, }, { name: "Composites", @@ -153,32 +143,26 @@ func TestLogging(t *testing.T) { `v.array.0=foo v.array.1=bar v.array.2.0=baz v.array.2.1=qux`, j: `{"v":{"doc":{"foo":"bar","baz":{"qux":"quux"}},"doc_raw":"RawDocument<1>",` + `"array":{"0":"foo","1":"bar","2":{"0":"baz","1":"qux"}}}}`, - m: ` - { - "doc": {"foo": "bar", "baz": {"qux": "quux"}}, - "doc_raw": RawDocument<1>, - "doc_empty": {}, - "array": ["foo", "bar", ["baz", "qux"]], - }`, - b: ` - { - "doc": { - "foo": "bar", - "baz": { - "qux": "quux", - }, - }, - "doc_raw": RawDocument<1>, - "doc_empty": {}, - "array": [ - "foo", - "bar", - [ - "baz", - "qux", - ], - ], - }`, + mi: ` + { + "doc": { + "foo": "bar", + "baz": { + "qux": "quux", + }, + }, + "doc_raw": RawDocument<1>, + "doc_empty": {}, + "array": [ + "foo", + "bar", + [ + "baz", + "qux", + ], + ], + }`, + m: `{"doc": {"foo": "bar", "baz": {"qux": "quux"}}, "doc_raw": RawDocument<1>, "doc_empty": {}, "array": ["foo", "bar", ["baz", "qux"]]}`, }, { name: "Nested", @@ -186,64 +170,57 @@ func TestLogging(t *testing.T) { t: `v.f.0.f.0.f.0.f.0.f.0.f.0.f.0.f.0.f.0.f.0=`, j: `{"v":{"f":{"0":{"f":{"0":{"f":{"0":{"f":{"0":{"f":{"0":{"f":{"0":` + `{"f":{"0":{"f":{"0":{"f":{"0":{"f":{"0":null}}}}}}}}}}}}}}}}}}}}}`, - m: ` - { - "f": [ - { - "f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [null]}]}]}]}]}]}]}]}], - }, - ], - }`, - b: ` - { - "f": [ - { - "f": [ - { - "f": [ - { - "f": [ - { - "f": [ - { - "f": [ - { - "f": [ - { - "f": [ - { - "f": [ - { - "f": [ - null, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }`, + mi: ` + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + { + "f": [ + null, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }`, + m: `{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [{"f": [null]}]}]}]}]}]}]}]}]}]}`, }, { name: "Raw", doc: RawDocument{42, 7}, t: `v=RawDocument<2>`, j: `{"v":"RawDocument<2>"}`, + mi: `RawDocument<2>`, m: `RawDocument<2>`, - b: `RawDocument<2>`, }, } { t.Run(tc.name, func(t *testing.T) { @@ -258,8 +235,8 @@ func TestLogging(t *testing.T) { m := LogMessage(tc.doc) assert.Equal(t, testutil.Unindent(tc.m), m, "actual LogMessage result:\n%s", m) - b := LogMessageBlock(tc.doc) - assert.Equal(t, testutil.Unindent(tc.b), b, "actual LogMessageBlock result:\n%s", b) + mi := LogMessageIndent(tc.doc) + assert.Equal(t, testutil.Unindent(tc.mi), mi, "actual LogMessageIndent result:\n%s", mi) }) } } diff --git a/wireclient/wireclient.go b/wireclient/wireclient.go index 7a124c6..8a8eb51 100644 --- a/wireclient/wireclient.go +++ b/wireclient/wireclient.go @@ -154,7 +154,7 @@ func (c *Conn) Read(ctx context.Context) (*wire.MsgHeader, wire.MsgBody, error) c.l.DebugContext( ctx, - fmt.Sprintf("<<<\n%s\n", body.StringBlock()), + fmt.Sprintf("<<<\n%s\n", body.StringIndent()), slog.Int("length", int(header.MessageLength)), slog.Int("id", int(header.RequestID)), slog.Int("response_to", int(header.ResponseTo)), @@ -170,7 +170,7 @@ func (c *Conn) Read(ctx context.Context) (*wire.MsgHeader, wire.MsgBody, error) func (c *Conn) Write(ctx context.Context, header *wire.MsgHeader, body wire.MsgBody) error { c.l.DebugContext( ctx, - fmt.Sprintf(">>>\n%s\n", body.StringBlock()), + fmt.Sprintf(">>>\n%s\n", body.StringIndent()), slog.Int("length", int(header.MessageLength)), slog.Int("id", int(header.RequestID)), slog.Int("response_to", int(header.ResponseTo)),