mirror of https://github.com/golang/go.git
Compare commits
6 Commits
4008f0338a
...
a68998afc7
| Author | SHA1 | Date |
|---|---|---|
|
|
a68998afc7 | |
|
|
49cdf0c42e | |
|
|
3bf1eecbd3 | |
|
|
8ed23a2936 | |
|
|
ef60769b46 | |
|
|
360edca70a |
|
|
@ -82,7 +82,7 @@ func newGCM(cipher Block, nonceSize, tagSize int) (AEAD, error) {
|
|||
|
||||
// NewGCMWithRandomNonce returns the given cipher wrapped in Galois Counter
|
||||
// Mode, with randomly-generated nonces. The cipher must have been created by
|
||||
// [aes.NewCipher].
|
||||
// [crypto/aes.NewCipher].
|
||||
//
|
||||
// It generates a random 96-bit nonce, which is prepended to the ciphertext by Seal,
|
||||
// and is extracted from the ciphertext by Open. The NonceSize of the AEAD is zero,
|
||||
|
|
|
|||
|
|
@ -138,7 +138,14 @@ func (d *Decoder) Reset(r io.Reader, opts ...Options) {
|
|||
case d.s.Flags.Get(jsonflags.WithinArshalCall):
|
||||
panic("jsontext: cannot reset Decoder passed to json.UnmarshalerFrom")
|
||||
}
|
||||
d.s.reset(nil, r, opts...)
|
||||
// If the decoder was previously aliasing a bytes.Buffer,
|
||||
// invalidate the alias to avoid writing into the bytes.Buffer's
|
||||
// internal buffer.
|
||||
b := d.s.buf[:0]
|
||||
if _, ok := d.s.rd.(*bytes.Buffer); ok {
|
||||
b = nil // avoid reusing b since it aliases the previous bytes.Buffer.
|
||||
}
|
||||
d.s.reset(b, r, opts...)
|
||||
}
|
||||
|
||||
func (d *decoderState) reset(b []byte, r io.Reader, opts ...Options) {
|
||||
|
|
|
|||
|
|
@ -1265,3 +1265,86 @@ func TestPeekableDecoder(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestDecoderReset tests that the decoder preserves its internal
|
||||
// buffer between Reset calls to avoid frequent allocations when reusing the decoder.
|
||||
// It ensures that the buffer capacity is maintained while avoiding aliasing
|
||||
// issues with bytes.Buffer.
|
||||
func TestDecoderReset(t *testing.T) {
|
||||
// Create a decoder with a reasonably large JSON input to ensure buffer growth
|
||||
largeJSON := `{"key1":"value1","key2":"value2","key3":"value3","key4":"value4","key5":"value5"}`
|
||||
dec := NewDecoder(strings.NewReader(largeJSON))
|
||||
|
||||
t.Run("Test capacity preservation", func(t *testing.T) {
|
||||
// Read the first JSON value to grow the internal buffer
|
||||
val1, err := dec.ReadValue()
|
||||
if err != nil {
|
||||
t.Fatalf("first ReadValue failed: %v", err)
|
||||
}
|
||||
if string(val1) != largeJSON {
|
||||
t.Fatalf("first ReadValue = %q, want %q", val1, largeJSON)
|
||||
}
|
||||
|
||||
// Get the buffer capacity after first use
|
||||
initialCapacity := cap(dec.s.buf)
|
||||
if initialCapacity == 0 {
|
||||
t.Fatalf("expected non-zero buffer capacity after first use")
|
||||
}
|
||||
|
||||
// Reset with a new reader - this should preserve the buffer capacity
|
||||
dec.Reset(strings.NewReader(largeJSON))
|
||||
|
||||
// Verify the buffer capacity is preserved (or at least not smaller)
|
||||
preservedCapacity := cap(dec.s.buf)
|
||||
if preservedCapacity < initialCapacity {
|
||||
t.Fatalf("buffer capacity reduced after Reset: got %d, want at least %d", preservedCapacity, initialCapacity)
|
||||
}
|
||||
|
||||
// Read the second JSON value to ensure the decoder still works correctly
|
||||
val2, err := dec.ReadValue()
|
||||
if err != nil {
|
||||
t.Fatalf("second ReadValue failed: %v", err)
|
||||
}
|
||||
if string(val2) != largeJSON {
|
||||
t.Fatalf("second ReadValue = %q, want %q", val2, largeJSON)
|
||||
}
|
||||
})
|
||||
|
||||
var bbBuf []byte
|
||||
t.Run("Test aliasing with bytes.Buffer", func(t *testing.T) {
|
||||
// Test with bytes.Buffer to verify proper aliasing behavior.
|
||||
bb := bytes.NewBufferString(largeJSON)
|
||||
dec.Reset(bb)
|
||||
bbBuf = bb.Bytes()
|
||||
|
||||
// Read the third JSON value to ensure functionality with bytes.Buffer
|
||||
val3, err := dec.ReadValue()
|
||||
if err != nil {
|
||||
t.Fatalf("fourth ReadValue failed: %v", err)
|
||||
}
|
||||
if string(val3) != largeJSON {
|
||||
t.Fatalf("fourth ReadValue = %q, want %q", val3, largeJSON)
|
||||
}
|
||||
// The decoder buffer should alias bytes.Buffer's internal buffer.
|
||||
if len(dec.s.buf) == 0 || len(bbBuf) == 0 || &dec.s.buf[0] != &bbBuf[0] {
|
||||
t.Fatalf("decoder buffer does not alias bytes.Buffer")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Test aliasing removed after Reset", func(t *testing.T) {
|
||||
// Reset with a new reader and verify the buffer is not aliased.
|
||||
dec.Reset(strings.NewReader(largeJSON))
|
||||
val4, err := dec.ReadValue()
|
||||
if err != nil {
|
||||
t.Fatalf("fifth ReadValue failed: %v", err)
|
||||
}
|
||||
if string(val4) != largeJSON {
|
||||
t.Fatalf("fourth ReadValue = %q, want %q", val4, largeJSON)
|
||||
}
|
||||
|
||||
// The decoder buffer should not alias the bytes.Buffer's internal buffer.
|
||||
if len(dec.s.buf) == 0 || len(bbBuf) == 0 || &dec.s.buf[0] == &bbBuf[0] {
|
||||
t.Fatalf("decoder buffer aliases bytes.Buffer")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
PACKAGE issue62640
|
||||
|
||||
IMPORTPATH
|
||||
testdata/issue62640
|
||||
|
||||
FILENAMES
|
||||
testdata/issue62640.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F()
|
||||
|
||||
//
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
PACKAGE issue62640
|
||||
|
||||
IMPORTPATH
|
||||
testdata/issue62640
|
||||
|
||||
FILENAMES
|
||||
testdata/issue62640.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F()
|
||||
|
||||
//
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
PACKAGE issue62640
|
||||
|
||||
IMPORTPATH
|
||||
testdata/issue62640
|
||||
|
||||
FILENAMES
|
||||
testdata/issue62640.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F()
|
||||
|
||||
//
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (S) F()
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2025 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue62640
|
||||
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F() {}
|
||||
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
|
@ -312,8 +312,10 @@ type heapArena struct {
|
|||
// during marking.
|
||||
pageSpecials [pagesPerArena / 8]uint8
|
||||
|
||||
// pageUseSpanDartboard is a bitmap that indicates which spans are
|
||||
// heap spans and also gcUsesSpanDartboard.
|
||||
// pageUseSpanInlineMarkBits is a bitmap where each bit corresponds
|
||||
// to a span, as only spans one page in size can have inline mark bits.
|
||||
// The bit indicates that the span has a spanInlineMarkBits struct
|
||||
// stored directly at the top end of the span's memory.
|
||||
pageUseSpanInlineMarkBits [pagesPerArena / 8]uint8
|
||||
|
||||
// checkmarks stores the debug.gccheckmark state. It is only
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2025 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package synctest_test
|
||||
|
||||
import "testing"
|
||||
|
||||
// helperLog is a t.Helper which logs.
|
||||
// Since it is a helper, the log prefix should contain
|
||||
// the caller's file, not helper_test.go.
|
||||
func helperLog(t *testing.T, s string) {
|
||||
t.Helper()
|
||||
t.Log(s)
|
||||
}
|
||||
|
|
@ -140,6 +140,18 @@ func TestRun(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestHelper(t *testing.T) {
|
||||
runTest(t, []string{"-test.v"}, func() {
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
helperLog(t, "log in helper")
|
||||
})
|
||||
}, `^=== RUN TestHelper
|
||||
synctest_test.go:.* log in helper
|
||||
--- PASS: TestHelper.*
|
||||
PASS
|
||||
$`)
|
||||
}
|
||||
|
||||
func wantPanic(t *testing.T, want string) {
|
||||
if e := recover(); e != nil {
|
||||
if got := fmt.Sprint(e); got != want {
|
||||
|
|
|
|||
|
|
@ -1261,6 +1261,9 @@ func (c *common) Skipped() bool {
|
|||
// When printing file and line information, that function will be skipped.
|
||||
// Helper may be called simultaneously from multiple goroutines.
|
||||
func (c *common) Helper() {
|
||||
if c.isSynctest {
|
||||
c = c.parent
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.helperPCs == nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue