yudai / gojsondiff

Go JSON Diff
Other
535 stars 81 forks source link

CompareObjects hangs on valid input #9

Open pteichman opened 7 years ago

pteichman commented 7 years ago

I found a pair of valid JSON inputs that cause Differ.CompareObjects to hang indefinitely.

[Edit: changing the link to a branch rather than specific commit]

I've added sanitized versions of those files and a hanging unit test over here: https://github.com/pteichman/gojsondiff/tree/infinite-hang

As an API request, would it be useful to be able to disable the substring diffing? For my use case it's enough to know that the values fail string equality checks. Or alternatively, should LCS calculation be part of the display logic rather than in the differ itself?

pteichman commented 7 years ago

And here's a goroutine dump while it's hanging. At least this time it was in reflect.DeepEqual, though that function itself runs fine on my two inputs. Maybe an infinite loop in the string similarity code?

SIGQUIT: quit PC=0x5f50b m=0

goroutine 0 [idle]: runtime.mach_semaphore_wait(0x7fff00000d03, 0x1, 0x55310, 0x7fff5fbff404, 0xffffffffffffffff, 0x5139e0, 0x7fff5fbff450, 0x55343, 0xffffffffffffffff, 0x513120, ...) /usr/local/go/src/runtime/sys_darwin_amd64.s:418 +0xb runtime.semasleep1(0xffffffffffffffff, 0x513120) /usr/local/go/src/runtime/os_darwin.go:435 +0x4b runtime.semasleep.func1() /usr/local/go/src/runtime/os_darwin.go:451 +0x33 runtime.systemstack(0x7fff5fbff478) /usr/local/go/src/runtime/asm_amd64.s:314 +0xab runtime.semasleep(0xffffffffffffffff, 0x0) /usr/local/go/src/runtime/os_darwin.go:452 +0x44 runtime.notesleep(0x514330) /usr/local/go/src/runtime/lock_sema.go:166 +0x9f runtime.stopm() /usr/local/go/src/runtime/proc.go:1594 +0xad runtime.findrunnable(0xc42001c000, 0x0) /usr/local/go/src/runtime/proc.go:2021 +0x228 runtime.schedule() /usr/local/go/src/runtime/proc.go:2120 +0x14c runtime.park_m(0xc420001040) /usr/local/go/src/runtime/proc.go:2183 +0x123 runtime.mcall(0x7fff5fbff670) /usr/local/go/src/runtime/asm_amd64.s:240 +0x5b

goroutine 1 [chan receive]: testing.(T).Run(0xc420092300, 0x37c0d8, 0xe, 0x3a6ba8, 0x5f215) /usr/local/go/src/testing/testing.go:647 +0x316 testing.RunTests.func1(0xc420092300) /usr/local/go/src/testing/testing.go:793 +0x6d testing.tRunner(0xc420092300, 0xc42003ce30) /usr/local/go/src/testing/testing.go:610 +0x81 testing.RunTests(0x3a6c28, 0x50b020, 0x1, 0x1, 0xf9ab) /usr/local/go/src/testing/testing.go:799 +0x2f5 testing.(M).Run(0xc42003cef8, 0x43) /usr/local/go/src/testing/testing.go:743 +0x85 main.main() github.com/yudai/gojsondiff/_test/_testmain.go:56 +0xc6

goroutine 17 [syscall, locked to thread]: runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2086 +0x1

goroutine 5 [syscall]: os/signal.signal_recv(0x0) /usr/local/go/src/runtime/sigqueue.go:116 +0x157 os/signal.loop() /usr/local/go/src/os/signal/signal_unix.go:22 +0x22 created by os/signal.init.1 /usr/local/go/src/os/signal/signal_unix.go:28 +0x41

goroutine 6 [runnable]: reflect.DeepEqual(0x302bc0, 0xc420376a24, 0x302bc0, 0xc4200987f0, 0x38d) /usr/local/go/src/reflect/deepequal.go:176 github.com/yudai/golcs.(lcs).Table(0xc4200dc300, 0x34fee0, 0x1, 0xc4200dc300) /Users/peter/go/src/github.com/yudai/golcs/golcs.go:55 +0x1e6 github.com/yudai/golcs.(lcs).Length(0xc4200dc300, 0xc4200dc300) /Users/peter/go/src/github.com/yudai/golcs/golcs.go:67 +0x2b github.com/yudai/gojsondiff.stringSimilarity(0xc420336000, 0xe3f9, 0xc420368000, 0xa247, 0x119101) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:394 +0x157 github.com/yudai/gojsondiff.(Modified).similarity(0xc4200168c0, 0xc4202c1170) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:290 +0x1b8 github.com/yudai/gojsondiff.similarityCache.Similarity(0x4f1f80, 0xc4200168c0, 0xbff0000000000000, 0xc420324a48) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:36 +0x50 github.com/yudai/gojsondiff.(TextDiff).Similarity(0xc420278060, 0x10)

:68 +0x59 github.com/yudai/gojsondiff.deltasSimilarity(0xc420366060, 0x1, 0x1, 0xc42030e780) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:383 +0x56 github.com/yudai/gojsondiff.(*Object).similarity(0xc420014240, 0x31e7e0) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:170 +0x41 github.com/yudai/gojsondiff.similarityCache.Similarity(0x4f2080, 0xc420014240, 0xbff0000000000000, 0x4f55c0) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:36 +0x50 github.com/yudai/gojsondiff.(*Object).Similarity(0xc420014240, 0x4) :35 +0x59 github.com/yudai/gojsondiff.deltasSimilarity(0xc42010f6e0, 0x2, 0x2, 0x0) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:383 +0x56 github.com/yudai/gojsondiff.(*Object).similarity(0xc420015640, 0x1121e) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:170 +0x41 github.com/yudai/gojsondiff.similarityCache.Similarity(0x4f2080, 0xc420015640, 0xbff0000000000000, 0x100000000000000) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:36 +0x50 github.com/yudai/gojsondiff.(*Object).Similarity(0xc420015640, 0x0) :35 +0x59 github.com/yudai/gojsondiff.deltasSimilarity(0xc42019bb30, 0x1, 0x1, 0xc4202c88b0) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:383 +0x56 github.com/yudai/gojsondiff.(*Object).similarity(0xc420015680, 0xc420377601) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:170 +0x41 github.com/yudai/gojsondiff.similarityCache.Similarity(0x4f2080, 0xc420015680, 0xbff0000000000000, 0x3204e0) /Users/peter/go/src/github.com/yudai/gojsondiff/deltas.go:36 +0x50 github.com/yudai/gojsondiff.(*Object).Similarity(0xc420015680, 0x2) :35 +0x59 github.com/yudai/gojsondiff.(*Differ).maximizeSimilarities(0xc420312040, 0xc42025d9c0, 0x1, 0x1, 0xc42025d9e0, 0x1, 0x1, 0xc42030eb58, 0x131078, 0xc420110780, ...) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:334 +0x522 github.com/yudai/gojsondiff.(*Differ).compareArrays(0xc420312040, 0xc420312830, 0x1, 0x1, 0xc420366830, 0x1, 0x1, 0x101, 0x198, 0xc4203249c8) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:218 +0x17d4 github.com/yudai/gojsondiff.(*Differ).compareValues(0xc420312040, 0x4f5600, 0xc420366870, 0x2fcbc0, 0xc42025d560, 0x2fcbc0, 0xc42025d8c0, 0x217, 0xc42030f340, 0x12b1ac) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:255 +0xcf1 github.com/yudai/gojsondiff.(*Differ).compareMaps(0xc420312040, 0xc4202c0a80, 0xc4202c10e0, 0x8, 0xc420312040, 0x0) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:95 +0x214 github.com/yudai/gojsondiff.(*Differ).CompareObjects(0xc420312040, 0xc4202c0a80, 0xc4202c10e0, 0xc42030f4d0, 0x23912a) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff.go:72 +0x43 github.com/yudai/gojsondiff_test.glob..func1.1.1.3.1() /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff_test.go:41 +0xce github.com/onsi/ginkgo/internal/leafnodes.(*runner).runSync(0xc42001ae40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) /Users/peter/go/src/github.com/onsi/ginkgo/internal/leafnodes/runner.go:109 +0x9c github.com/onsi/ginkgo/internal/leafnodes.(*runner).run(0xc42001ae40, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) /Users/peter/go/src/github.com/onsi/ginkgo/internal/leafnodes/runner.go:63 +0xe1 github.com/onsi/ginkgo/internal/leafnodes.(*ItNode).Run(0xc42010f320, 0x4f1e00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) /Users/peter/go/src/github.com/onsi/ginkgo/internal/leafnodes/it_node.go:25 +0x64 github.com/onsi/ginkgo/internal/spec.(*Spec).runSample(0xc4201124e0, 0x0, 0x4f1e00, 0xc4200111d0) /Users/peter/go/src/github.com/onsi/ginkgo/internal/spec/spec.go:176 +0x4fd github.com/onsi/ginkgo/internal/spec.(*Spec).Run(0xc4201124e0, 0x4f1e00, 0xc4200111d0) /Users/peter/go/src/github.com/onsi/ginkgo/internal/spec/spec.go:127 +0xd4 github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpec(0xc4201a79e0, 0xc4201124e0, 0xc420041b01) /Users/peter/go/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:172 +0xed github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpecs(0xc4201a79e0, 0x3a6b01) /Users/peter/go/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:142 +0x2b3 github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).Run(0xc4201a79e0, 0x10) /Users/peter/go/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:61 +0xf0 github.com/onsi/ginkgo/internal/suite.(*Suite).Run(0xc420016fa0, 0x1148348, 0xc4200923c0, 0x37ce84, 0x10, 0xc42019b530, 0x1, 0x1, 0x4f6d40, 0xc4200111d0, ...) /Users/peter/go/src/github.com/onsi/ginkgo/internal/suite/suite.go:59 +0x23b github.com/onsi/ginkgo.RunSpecsWithCustomReporters(0x4f2c40, 0xc4200923c0, 0x37ce84, 0x10, 0xc42030bf00, 0x1, 0x1, 0x0) /Users/peter/go/src/github.com/onsi/ginkgo/ginkgo_dsl.go:218 +0x27b github.com/onsi/ginkgo.RunSpecs(0x4f2c40, 0xc4200923c0, 0x37ce84, 0x10, 0xc42c529adc) /Users/peter/go/src/github.com/onsi/ginkgo/ginkgo_dsl.go:199 +0x208 github.com/yudai/gojsondiff_test.TestGojsondiff(0xc4200923c0) /Users/peter/go/src/github.com/yudai/gojsondiff/gojsondiff_suite_test.go:12 +0x64 testing.tRunner(0xc4200923c0, 0x3a6ba8) /usr/local/go/src/testing/testing.go:610 +0x81 created by testing.(*T).Run /usr/local/go/src/testing/testing.go:646 +0x2ec goroutine 7 [chan receive]: github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).registerForInterrupts(0xc4201a79e0) /Users/peter/go/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:194 +0x13f created by github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).Run /Users/peter/go/src/github.com/onsi/ginkgo/internal/specrunner/spec_runner.go:56 +0x74 goroutine 18 [select, locked to thread]: runtime.gopark(0x3a7358, 0x0, 0x3778ec, 0x6, 0x18, 0x2) /usr/local/go/src/runtime/proc.go:259 +0x13a runtime.selectgoImpl(0xc420028730, 0x0, 0x18) /usr/local/go/src/runtime/select.go:423 +0x11d9 runtime.selectgo(0xc420028730) /usr/local/go/src/runtime/select.go:238 +0x1c runtime.ensureSigM.func1() /usr/local/go/src/runtime/signal1_unix.go:304 +0x2d1 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2086 +0x1 rax 0xe rbx 0x514220 rcx 0x7fff5fbff3f0 rdx 0x7fff5fbff478 rdi 0xd03 rsi 0xc420025500 rbp 0x7fff5fbff428 rsp 0x7fff5fbff3f0 r8 0xc420001040 r9 0x1 r10 0x223abe0 r11 0x286 r12 0x1 r13 0x1 r14 0x1 r15 0x406ce8 rip 0x5f50b rflags 0x286 cs 0x7 fs 0x0 gs 0x0 exit status 2 FAIL github.com/yudai/gojsondiff 15.962s
pteichman commented 7 years ago

This may be a bug / pathological input in golcs instead.