-
Notifications
You must be signed in to change notification settings - Fork 51
json: fix cycle detection #153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
e960845
dabc507
f786a42
d8717df
722d2e3
b34b8b9
41dfddc
40c79bc
396975c
9aaaa4b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,10 @@ package json | |
|
|
||
| import ( | ||
| "bytes" | ||
| "fmt" | ||
| "path" | ||
| "reflect" | ||
| "runtime" | ||
| "sync" | ||
| "testing" | ||
| ) | ||
|
|
@@ -68,3 +71,30 @@ func errorWithPrefixes(t *testing.T, prefixes []any, format string, elements ... | |
| } | ||
| t.Errorf(fullFormat, allElements...) | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // Copyright 2010 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. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Want to share what file these were taken from?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The strategy has been (I didn't come up with it, but am continuing it):
This golang_shim_test.go serves to fulfill point 2. |
||
|
|
||
| // CaseName is a case name annotated with a file and line. | ||
| type CaseName struct { | ||
| Name string | ||
| Where CasePos | ||
| } | ||
|
|
||
| // Name annotates a case name with the file and line of the caller. | ||
| func Name(s string) (c CaseName) { | ||
| c.Name = s | ||
| runtime.Callers(2, c.Where.pc[:]) | ||
| return c | ||
| } | ||
|
|
||
| // CasePos represents a file and line number. | ||
| type CasePos struct{ pc [1]uintptr } | ||
|
|
||
| func (pos CasePos) String() string { | ||
| frames := runtime.CallersFrames(pos.pc[:]) | ||
| frame, _ := frames.Next() | ||
| return fmt.Sprintf("%s:%d", path.Base(frame.File), frame.Line) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you confirm that these tests broke with the behavior on tip before you applied your patches? Ie, that the patches fix the tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sure did. Essentially the main branch of segmentio/encoding/json fails all of the stdlib cycle tests. It tried to implement detection of cycles involving regular pointers, but failed at that goal, and since there hadn't been any meaningful tests covering cycle detection, that broken feature went unnoticed.
This PR fixes not only cycle detection involving pointers, but also adds (working) support for data cycles involving maps and slices, as well as codec generation support for recursively defined slices, e.g.
type T []T. There may be other hypothetical cases that aren't yet covered, but as of this PR, segmentio/encoding/json has parity with the stdlib encoding/json (at least in terms of passing all the relevant stdlib tests) for any kind of cycle.