debug_test.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605
  1. /*
  2. * ECAL
  3. *
  4. * Copyright 2020 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package interpreter
  11. import (
  12. "encoding/json"
  13. "fmt"
  14. "strconv"
  15. "strings"
  16. "sync"
  17. "testing"
  18. "time"
  19. "devt.de/krotik/common/errorutil"
  20. "devt.de/krotik/ecal/scope"
  21. "devt.de/krotik/ecal/util"
  22. )
  23. func TestSimpleDebugging(t *testing.T) {
  24. var err error
  25. defer func() {
  26. testDebugger = nil
  27. }()
  28. testDebugger = NewECALDebugger(nil)
  29. _, err = testDebugger.HandleInput("break ECALEvalTest:3")
  30. errorutil.AssertOk(err)
  31. _, err = testDebugger.HandleInput("break ECALEvalTest:4")
  32. errorutil.AssertOk(err)
  33. _, err = testDebugger.HandleInput("disablebreak ECALEvalTest:4")
  34. errorutil.AssertOk(err)
  35. wg := &sync.WaitGroup{}
  36. wg.Add(1)
  37. var tid uint64
  38. go func() {
  39. _, err = UnitTestEval(`
  40. log("test1")
  41. log("test2")
  42. log("test3")
  43. `, nil)
  44. if err != nil {
  45. t.Error(err)
  46. }
  47. testDebugger.RecordThreadFinished(tid)
  48. wg.Done()
  49. }()
  50. tid = waitForThreadSuspension(t)
  51. out, err := testDebugger.HandleInput(fmt.Sprintf("status"))
  52. outBytes, _ := json.MarshalIndent(out, "", " ")
  53. outString := string(outBytes)
  54. if err != nil || outString != `{
  55. "breakonstart": false,
  56. "breakpoints": {
  57. "ECALEvalTest:3": true,
  58. "ECALEvalTest:4": false
  59. },
  60. "sources": [
  61. "ECALEvalTest"
  62. ],
  63. "threads": {
  64. "1": {
  65. "callStack": [],
  66. "error": null,
  67. "threadRunning": false
  68. }
  69. }
  70. }` {
  71. t.Error("Unexpected result:", outString, err)
  72. return
  73. }
  74. out, err = testDebugger.HandleInput(fmt.Sprintf("describe %v", tid))
  75. outBytes, _ = json.MarshalIndent(out, "", " ")
  76. outString = string(outBytes)
  77. if err != nil || outString != `{
  78. "callStack": [],
  79. "callStackNode": [],
  80. "callStackVsSnapshot": [],
  81. "callStackVsSnapshotGlobal": [],
  82. "code": "log(\"test2\")",
  83. "error": null,
  84. "node": {
  85. "allowescapes": false,
  86. "children": [
  87. {
  88. "children": [
  89. {
  90. "allowescapes": true,
  91. "id": 5,
  92. "identifier": false,
  93. "line": 3,
  94. "linepos": 5,
  95. "name": "string",
  96. "pos": 18,
  97. "source": "ECALEvalTest",
  98. "value": "test2"
  99. }
  100. ],
  101. "name": "funccall"
  102. }
  103. ],
  104. "id": 7,
  105. "identifier": true,
  106. "line": 3,
  107. "linepos": 1,
  108. "name": "identifier",
  109. "pos": 14,
  110. "source": "ECALEvalTest",
  111. "value": "log"
  112. },
  113. "threadRunning": false,
  114. "vs": {},
  115. "vsGlobal": {}
  116. }` {
  117. t.Error("Unexpected result:", outString, err)
  118. return
  119. }
  120. // Continue until the end
  121. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v Resume", tid))
  122. errorutil.AssertOk(err)
  123. wg.Wait()
  124. if err != nil || testlogger.String() != `
  125. test1
  126. test2
  127. test3`[1:] {
  128. t.Error("Unexpected result:", testlogger.String(), err)
  129. return
  130. }
  131. _, err = testDebugger.HandleInput("rmbreak ECALEvalTest:4")
  132. errorutil.AssertOk(err)
  133. out, err = testDebugger.HandleInput(fmt.Sprintf("status"))
  134. outBytes, _ = json.MarshalIndent(out, "", " ")
  135. outString = string(outBytes)
  136. if err != nil || outString != `{
  137. "breakonstart": false,
  138. "breakpoints": {
  139. "ECALEvalTest:3": true
  140. },
  141. "sources": [
  142. "ECALEvalTest"
  143. ],
  144. "threads": {}
  145. }` {
  146. t.Error("Unexpected result:", outString, err)
  147. return
  148. }
  149. _, err = testDebugger.HandleInput("break ECALEvalTest:4")
  150. errorutil.AssertOk(err)
  151. _, err = testDebugger.HandleInput("rmbreak ECALEvalTest")
  152. errorutil.AssertOk(err)
  153. out, err = testDebugger.HandleInput(fmt.Sprintf("status"))
  154. outBytes, _ = json.MarshalIndent(out, "", " ")
  155. outString = string(outBytes)
  156. if err != nil || outString != `{
  157. "breakonstart": false,
  158. "breakpoints": {},
  159. "sources": [
  160. "ECALEvalTest"
  161. ],
  162. "threads": {}
  163. }` {
  164. t.Error("Unexpected result:", outString, err)
  165. return
  166. }
  167. }
  168. func TestDebugReset(t *testing.T) {
  169. var err error
  170. defer func() {
  171. testDebugger = nil
  172. }()
  173. testDebugger = NewECALDebugger(nil)
  174. if _, err = testDebugger.HandleInput("break ECALEvalTest:3"); err != nil {
  175. t.Error("Unexpected result:", err)
  176. return
  177. }
  178. wg := &sync.WaitGroup{}
  179. wg.Add(1)
  180. go func() {
  181. defer wg.Done()
  182. _, err = UnitTestEval(`
  183. log("test1")
  184. log("test2")
  185. log("test3")
  186. `, nil)
  187. if err != nil {
  188. t.Error(err)
  189. }
  190. }()
  191. waitForThreadSuspension(t)
  192. out, err := testDebugger.HandleInput(fmt.Sprintf("status"))
  193. outBytes, _ := json.MarshalIndent(out, "", " ")
  194. outString := string(outBytes)
  195. if err != nil || outString != `{
  196. "breakonstart": false,
  197. "breakpoints": {
  198. "ECALEvalTest:3": true
  199. },
  200. "sources": [
  201. "ECALEvalTest"
  202. ],
  203. "threads": {
  204. "1": {
  205. "callStack": [],
  206. "error": null,
  207. "threadRunning": false
  208. }
  209. }
  210. }` {
  211. t.Error("Unexpected result:", outString, err)
  212. return
  213. }
  214. testDebugger.StopThreads(100 * time.Millisecond)
  215. wg.Wait()
  216. if err != nil || testlogger.String() != `
  217. test1
  218. test2`[1:] {
  219. t.Error("Unexpected result:", testlogger.String(), err)
  220. return
  221. }
  222. }
  223. func TestErrorStop(t *testing.T) {
  224. var err, evalError error
  225. defer func() {
  226. testDebugger = nil
  227. }()
  228. testDebugger = NewECALDebugger(nil)
  229. testDebugger.BreakOnError(true)
  230. if _, err = testDebugger.HandleInput("break ECALEvalTest:8"); err != nil {
  231. t.Error("Unexpected result:", err)
  232. return
  233. }
  234. wg := &sync.WaitGroup{}
  235. wg.Add(1)
  236. go func() {
  237. defer wg.Done()
  238. _, evalError = UnitTestEval(`
  239. func err () {
  240. raise("foo")
  241. }
  242. log("test1")
  243. log("test2")
  244. err()
  245. log("test3")
  246. `, nil)
  247. }()
  248. waitForThreadSuspension(t)
  249. out, err := testDebugger.HandleInput(fmt.Sprintf("status"))
  250. outBytes, _ := json.MarshalIndent(out, "", " ")
  251. outString := string(outBytes)
  252. if err != nil || outString != `{
  253. "breakonstart": false,
  254. "breakpoints": {
  255. "ECALEvalTest:8": true
  256. },
  257. "sources": [
  258. "ECALEvalTest"
  259. ],
  260. "threads": {
  261. "1": {
  262. "callStack": [
  263. "err() (ECALEvalTest:7)"
  264. ],
  265. "error": {
  266. "Data": null,
  267. "Detail": "",
  268. "Environment": {},
  269. "Node": {
  270. "Name": "identifier",
  271. "Token": {
  272. "ID": 7,
  273. "Pos": 16,
  274. "Val": "raise",
  275. "Identifier": true,
  276. "AllowEscapes": false,
  277. "PrefixNewlines": 1,
  278. "Lsource": "ECALEvalTest",
  279. "Lline": 3,
  280. "Lpos": 2
  281. },
  282. "Meta": null,
  283. "Children": [
  284. {
  285. "Name": "funccall",
  286. "Token": null,
  287. "Meta": null,
  288. "Children": [
  289. {
  290. "Name": "string",
  291. "Token": {
  292. "ID": 5,
  293. "Pos": 22,
  294. "Val": "foo",
  295. "Identifier": false,
  296. "AllowEscapes": true,
  297. "PrefixNewlines": 0,
  298. "Lsource": "ECALEvalTest",
  299. "Lline": 3,
  300. "Lpos": 8
  301. },
  302. "Meta": null,
  303. "Children": [],
  304. "Runtime": {}
  305. }
  306. ],
  307. "Runtime": {}
  308. }
  309. ],
  310. "Runtime": {}
  311. },
  312. "Source": "ECALTestRuntime (ECALEvalTest)",
  313. "Trace": null,
  314. "Type": "foo"
  315. },
  316. "threadRunning": false
  317. }
  318. }
  319. }` {
  320. t.Error("Unexpected result:", outString, err)
  321. return
  322. }
  323. if _, err = testDebugger.HandleInput(fmt.Sprintf("cont 1 Resume")); err != nil {
  324. t.Error("Unexpected result:", err)
  325. return
  326. }
  327. wg.Wait()
  328. if evalError == nil || testlogger.String() != `
  329. test1
  330. test2`[1:] || evalError.Error() != "ECAL error in ECALTestRuntime (ECALEvalTest): foo () (Line:3 Pos:2)" {
  331. t.Error("Unexpected result:", testlogger.String(), evalError, err)
  332. return
  333. }
  334. }
  335. func TestConcurrentDebugging(t *testing.T) {
  336. var err error
  337. defer func() {
  338. testDebugger = nil
  339. }()
  340. testDebugger = NewECALDebugger(nil)
  341. if _, err = testDebugger.HandleInput("break ECALEvalTest:5"); err != nil {
  342. t.Error("Unexpected result:", err)
  343. return
  344. }
  345. wg := &sync.WaitGroup{}
  346. wg.Add(2)
  347. erp := NewECALRuntimeProvider("ECALTestRuntime", nil, nil)
  348. vs := scope.NewScope(scope.GlobalScope)
  349. go func() {
  350. _, err = UnitTestEvalWithRuntimeProvider(`
  351. a := 1
  352. b := 1
  353. func test1() {
  354. log("test3")
  355. b := a + 1
  356. }
  357. log("test1")
  358. log("test2")
  359. test1()
  360. log("test4")
  361. `, vs, erp)
  362. if err != nil {
  363. t.Error(err)
  364. }
  365. wg.Done()
  366. }()
  367. go func() {
  368. _, err = UnitTestEvalWithRuntimeProvider(`
  369. a := 1
  370. c := 1
  371. func test2() {
  372. log("test3")
  373. c := a + 1
  374. }
  375. log("test1")
  376. log("test2")
  377. test2()
  378. log("test4")
  379. mutex a { mutex a { log("test5") } }
  380. `, vs, erp)
  381. if err != nil {
  382. t.Error(err)
  383. }
  384. wg.Done()
  385. }()
  386. waitForAllThreadSuspension(t)
  387. out, err := testDebugger.HandleInput(fmt.Sprintf("status"))
  388. outBytes, _ := json.MarshalIndent(out, "", " ")
  389. outString := string(outBytes)
  390. if err != nil || (outString != `{
  391. "breakonstart": false,
  392. "breakpoints": {
  393. "ECALEvalTest:5": true
  394. },
  395. "sources": [
  396. "ECALEvalTest"
  397. ],
  398. "threads": {
  399. "1": {
  400. "callStack": [
  401. "test1() (ECALEvalTest:10)"
  402. ],
  403. "error": null,
  404. "threadRunning": false
  405. },
  406. "2": {
  407. "callStack": [
  408. "test2() (ECALEvalTest:10)"
  409. ],
  410. "error": null,
  411. "threadRunning": false
  412. }
  413. }
  414. }` && outString != `{
  415. "breakonstart": false,
  416. "breakpoints": {
  417. "ECALEvalTest:5": true
  418. },
  419. "sources": [
  420. "ECALEvalTest"
  421. ],
  422. "threads": {
  423. "1": {
  424. "callStack": [
  425. "test2() (ECALEvalTest:10)"
  426. ],
  427. "error": null,
  428. "threadRunning": false
  429. },
  430. "2": {
  431. "callStack": [
  432. "test1() (ECALEvalTest:10)"
  433. ],
  434. "error": null,
  435. "threadRunning": false
  436. }
  437. }
  438. }`) {
  439. t.Error("Unexpected result:", outString, err)
  440. return
  441. }
  442. ls, err := testDebugger.HandleInput(fmt.Sprintf("lockstate"))
  443. lsBytes, _ := json.MarshalIndent(ls, "", " ")
  444. lsString := string(lsBytes)
  445. if lsString != `{
  446. "log": [],
  447. "owners": {}
  448. }` {
  449. t.Error("Unexpected result:", lsString)
  450. return
  451. }
  452. // Continue until the end
  453. if _, err := testDebugger.HandleInput(fmt.Sprintf("cont 1 Resume")); err != nil {
  454. t.Error("Unexpected result:", err)
  455. return
  456. }
  457. if _, err := testDebugger.HandleInput(fmt.Sprintf("cont 2 Resume")); err != nil {
  458. t.Error("Unexpected result:", err)
  459. return
  460. }
  461. wg.Wait()
  462. if vs.String() != `GlobalScope {
  463. a (float64) : 1
  464. b (float64) : 2
  465. c (float64) : 2
  466. test1 (*interpreter.function) : ecal.function: test1 (Line 4, Pos 1)
  467. test2 (*interpreter.function) : ecal.function: test2 (Line 4, Pos 1)
  468. block: mutex (Line:12 Pos:1) {
  469. block: mutex (Line:12 Pos:11) {
  470. }
  471. }
  472. }` {
  473. t.Error("Unexpected result:", vs)
  474. return
  475. }
  476. ls, err = testDebugger.HandleInput(fmt.Sprintf("lockstate"))
  477. lsBytes, _ = json.MarshalIndent(ls, "", " ")
  478. lsString = string(lsBytes)
  479. if !strings.Contains(lsString, "took lock a with owner") || !strings.Contains(lsString, "attempted to take lock a twice") {
  480. t.Error("Unexpected result:", lsString)
  481. return
  482. }
  483. }
  484. func waitForThreadSuspension(t *testing.T) uint64 {
  485. var tid uint64
  486. for i := 0; i < 100; i++ {
  487. state, err := testDebugger.HandleInput("status")
  488. errorutil.AssertOk(err)
  489. threads := state.(map[string]interface{})["threads"].(map[string]map[string]interface{})
  490. if len(threads) > 0 {
  491. for threadID, status := range threads {
  492. if r, ok := status["threadRunning"]; ok && !r.(bool) {
  493. threadIDNum, _ := strconv.ParseInt(threadID, 10, 0)
  494. tid = uint64(threadIDNum)
  495. return tid
  496. }
  497. }
  498. }
  499. time.Sleep(1 * time.Millisecond)
  500. }
  501. panic("No suspended thread")
  502. }
  503. func waitForAllThreadSuspension(t *testing.T) uint64 {
  504. var tid uint64
  505. for i := 0; i < 100; i++ {
  506. state, err := testDebugger.HandleInput("status")
  507. errorutil.AssertOk(err)
  508. threads := state.(map[string]interface{})["threads"].(map[string]map[string]interface{})
  509. if len(threads) > 0 {
  510. allSuspended := true
  511. for _, status := range threads {
  512. if r, ok := status["threadRunning"]; ok && !r.(bool) {
  513. allSuspended = false
  514. break
  515. }
  516. }
  517. if allSuspended {
  518. break
  519. }
  520. }
  521. time.Sleep(1 * time.Millisecond)
  522. }
  523. return tid
  524. }
  525. func TestStepDebugging(t *testing.T) {
  526. var err error
  527. defer func() {
  528. testDebugger = nil
  529. }()
  530. testDebugger = NewECALDebugger(nil)
  531. code := `
  532. log("start")
  533. func fa(x) {
  534. a := 1
  535. log("a enter")
  536. fb(x)
  537. log("a exit")
  538. }
  539. func fb(x) {
  540. b := 2
  541. log("b enter")
  542. fc()
  543. fc(fc())
  544. log("b exit")
  545. }
  546. func fc() {
  547. c := 3
  548. log("c enter")
  549. log("c exit")
  550. }
  551. fa(1)
  552. func e() {
  553. log("e()")
  554. }
  555. func d() {
  556. e()
  557. }
  558. d(d())
  559. log("finish")
  560. `
  561. _, err = testDebugger.HandleInput("break ECALEvalTest:10")
  562. errorutil.AssertOk(err)
  563. _, err = testDebugger.HandleInput("breakonstart true")
  564. errorutil.AssertOk(err)
  565. wg := &sync.WaitGroup{}
  566. wg.Add(1)
  567. go func() {
  568. _, err = UnitTestEval(code, nil)
  569. if err != nil {
  570. t.Error(err)
  571. }
  572. wg.Done()
  573. }()
  574. tid := waitForThreadSuspension(t)
  575. if state := getDebuggerState(tid, t); state != `{
  576. "breakpoints": {
  577. "ECALEvalTest:10": true
  578. },
  579. "code": "log(\"start\")",
  580. "threads": {
  581. "1": {
  582. "callStack": [],
  583. "error": null,
  584. "threadRunning": false
  585. }
  586. },
  587. "vs": {}
  588. }` {
  589. t.Error("Unexpected state:", state)
  590. return
  591. }
  592. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v resume", tid))
  593. errorutil.AssertOk(err)
  594. tid = waitForThreadSuspension(t)
  595. if state := getDebuggerState(tid, t); state != `{
  596. "breakpoints": {
  597. "ECALEvalTest:10": true
  598. },
  599. "code": "b := 2",
  600. "threads": {
  601. "1": {
  602. "callStack": [
  603. "fa(1) (ECALEvalTest:21)",
  604. "fb(x) (ECALEvalTest:6)"
  605. ],
  606. "error": null,
  607. "threadRunning": false
  608. }
  609. },
  610. "vs": {
  611. "x": 1
  612. }
  613. }` {
  614. t.Error("Unexpected state:", state)
  615. return
  616. }
  617. // Step in without a function
  618. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v stepin", tid))
  619. errorutil.AssertOk(err)
  620. tid = waitForThreadSuspension(t)
  621. if state := getDebuggerState(tid, t); state != `{
  622. "breakpoints": {
  623. "ECALEvalTest:10": true
  624. },
  625. "code": "log(\"b enter\")",
  626. "threads": {
  627. "1": {
  628. "callStack": [
  629. "fa(1) (ECALEvalTest:21)",
  630. "fb(x) (ECALEvalTest:6)"
  631. ],
  632. "error": null,
  633. "threadRunning": false
  634. }
  635. },
  636. "vs": {
  637. "b": 2,
  638. "x": 1
  639. }
  640. }` {
  641. t.Error("Unexpected state:", state)
  642. return
  643. }
  644. // Normal step over
  645. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v stepover", tid))
  646. errorutil.AssertOk(err)
  647. tid = waitForThreadSuspension(t)
  648. if state := getDebuggerState(tid, t); state != `{
  649. "breakpoints": {
  650. "ECALEvalTest:10": true
  651. },
  652. "code": "fc()",
  653. "threads": {
  654. "1": {
  655. "callStack": [
  656. "fa(1) (ECALEvalTest:21)",
  657. "fb(x) (ECALEvalTest:6)"
  658. ],
  659. "error": null,
  660. "threadRunning": false
  661. }
  662. },
  663. "vs": {
  664. "b": 2,
  665. "x": 1
  666. }
  667. }` {
  668. t.Error("Unexpected state:", state)
  669. return
  670. }
  671. // Normal step in
  672. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v stepin", tid))
  673. errorutil.AssertOk(err)
  674. tid = waitForThreadSuspension(t)
  675. if state := getDebuggerState(tid, t); state != `{
  676. "breakpoints": {
  677. "ECALEvalTest:10": true
  678. },
  679. "code": "c := 3",
  680. "threads": {
  681. "1": {
  682. "callStack": [
  683. "fa(1) (ECALEvalTest:21)",
  684. "fb(x) (ECALEvalTest:6)",
  685. "fc() (ECALEvalTest:12)"
  686. ],
  687. "error": null,
  688. "threadRunning": false
  689. }
  690. },
  691. "vs": {}
  692. }` {
  693. t.Error("Unexpected state:", state)
  694. return
  695. }
  696. // Normal step out
  697. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v stepout", tid))
  698. errorutil.AssertOk(err)
  699. tid = waitForThreadSuspension(t)
  700. if state := getDebuggerState(tid, t); state != `{
  701. "breakpoints": {
  702. "ECALEvalTest:10": true
  703. },
  704. "code": "fc(fc())",
  705. "threads": {
  706. "1": {
  707. "callStack": [
  708. "fa(1) (ECALEvalTest:21)",
  709. "fb(x) (ECALEvalTest:6)"
  710. ],
  711. "error": null,
  712. "threadRunning": false
  713. }
  714. },
  715. "vs": {
  716. "b": 2,
  717. "x": 1
  718. }
  719. }` {
  720. t.Error("Unexpected state:", state)
  721. return
  722. }
  723. // Step in and step out - we should end up on the same line as before
  724. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v stepin", tid))
  725. errorutil.AssertOk(err)
  726. testStepDebugging2(t, testDebugger, wg)
  727. }
  728. func testStepDebugging2(t *testing.T, testDebugger util.ECALDebugger, wg *sync.WaitGroup) {
  729. tid := waitForThreadSuspension(t)
  730. if state := getDebuggerState(tid, t); state != `{
  731. "breakpoints": {
  732. "ECALEvalTest:10": true
  733. },
  734. "code": "c := 3",
  735. "threads": {
  736. "1": {
  737. "callStack": [
  738. "fa(1) (ECALEvalTest:21)",
  739. "fb(x) (ECALEvalTest:6)",
  740. "fc() (ECALEvalTest:13)"
  741. ],
  742. "error": null,
  743. "threadRunning": false
  744. }
  745. },
  746. "vs": {}
  747. }` {
  748. t.Error("Unexpected state:", state)
  749. return
  750. }
  751. _, err := testDebugger.HandleInput(fmt.Sprintf("cont %v stepout", tid))
  752. errorutil.AssertOk(err)
  753. tid = waitForThreadSuspension(t)
  754. if state := getDebuggerState(tid, t); state != `{
  755. "breakpoints": {
  756. "ECALEvalTest:10": true
  757. },
  758. "code": "fc(fc())",
  759. "threads": {
  760. "1": {
  761. "callStack": [
  762. "fa(1) (ECALEvalTest:21)",
  763. "fb(x) (ECALEvalTest:6)"
  764. ],
  765. "error": null,
  766. "threadRunning": false
  767. }
  768. },
  769. "vs": {
  770. "b": 2,
  771. "x": 1
  772. }
  773. }` {
  774. t.Error("Unexpected state:", state)
  775. return
  776. }
  777. // Normal step out
  778. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v stepout", tid))
  779. errorutil.AssertOk(err)
  780. tid = waitForThreadSuspension(t)
  781. if state := getDebuggerState(tid, t); state != `{
  782. "breakpoints": {
  783. "ECALEvalTest:10": true
  784. },
  785. "code": "log(\"a exit\")",
  786. "threads": {
  787. "1": {
  788. "callStack": [
  789. "fa(1) (ECALEvalTest:21)"
  790. ],
  791. "error": null,
  792. "threadRunning": false
  793. }
  794. },
  795. "vs": {
  796. "a": 1,
  797. "x": 1
  798. }
  799. }` {
  800. t.Error("Unexpected state:", state)
  801. return
  802. }
  803. // Set a new breakpoint
  804. _, err = testDebugger.HandleInput("break ECALEvalTest:28")
  805. errorutil.AssertOk(err)
  806. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v Resume", tid))
  807. errorutil.AssertOk(err)
  808. tid = waitForThreadSuspension(t)
  809. if state := getDebuggerState(tid, t); state != `{
  810. "breakpoints": {
  811. "ECALEvalTest:10": true,
  812. "ECALEvalTest:28": true
  813. },
  814. "code": "d(d())",
  815. "threads": {
  816. "1": {
  817. "callStack": [],
  818. "error": null,
  819. "threadRunning": false
  820. }
  821. },
  822. "vs": {
  823. "d": "ecal.function: d (Line 25, Pos 1)",
  824. "e": "ecal.function: e (Line 22, Pos 1)",
  825. "fa": "ecal.function: fa (Line 3, Pos 1)",
  826. "fb": "ecal.function: fb (Line 9, Pos 1)",
  827. "fc": "ecal.function: fc (Line 16, Pos 1)"
  828. }
  829. }` {
  830. t.Error("Unexpected state:", state)
  831. return
  832. }
  833. // Normal step over
  834. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v stepover", tid))
  835. errorutil.AssertOk(err)
  836. tid = waitForThreadSuspension(t)
  837. if state := getDebuggerState(tid, t); state != `{
  838. "breakpoints": {
  839. "ECALEvalTest:10": true,
  840. "ECALEvalTest:28": true
  841. },
  842. "code": "d(d())",
  843. "threads": {
  844. "1": {
  845. "callStack": [],
  846. "error": null,
  847. "threadRunning": false
  848. }
  849. },
  850. "vs": {
  851. "d": "ecal.function: d (Line 25, Pos 1)",
  852. "e": "ecal.function: e (Line 22, Pos 1)",
  853. "fa": "ecal.function: fa (Line 3, Pos 1)",
  854. "fb": "ecal.function: fb (Line 9, Pos 1)",
  855. "fc": "ecal.function: fc (Line 16, Pos 1)"
  856. }
  857. }` {
  858. t.Error("Unexpected state:", state)
  859. return
  860. }
  861. if _, err := testDebugger.HandleInput(fmt.Sprintf("cont %v stepover", tid)); err != nil {
  862. t.Error("Unexpected result:", err)
  863. return
  864. }
  865. tid = waitForThreadSuspension(t)
  866. if state := getDebuggerState(tid, t); state != `{
  867. "breakpoints": {
  868. "ECALEvalTest:10": true,
  869. "ECALEvalTest:28": true
  870. },
  871. "code": "log(\"finish\")",
  872. "threads": {
  873. "1": {
  874. "callStack": [],
  875. "error": null,
  876. "threadRunning": false
  877. }
  878. },
  879. "vs": {
  880. "d": "ecal.function: d (Line 25, Pos 1)",
  881. "e": "ecal.function: e (Line 22, Pos 1)",
  882. "fa": "ecal.function: fa (Line 3, Pos 1)",
  883. "fb": "ecal.function: fb (Line 9, Pos 1)",
  884. "fc": "ecal.function: fc (Line 16, Pos 1)"
  885. }
  886. }` {
  887. t.Error("Unexpected state:", state)
  888. return
  889. }
  890. // Continue until the end
  891. _, err = testDebugger.HandleInput(fmt.Sprintf("cont %v Resume", tid))
  892. errorutil.AssertOk(err)
  893. wg.Wait()
  894. if err != nil || testlogger.String() != `
  895. start
  896. a enter
  897. b enter
  898. c enter
  899. c exit
  900. c enter
  901. c exit
  902. c enter
  903. c exit
  904. b exit
  905. a exit
  906. e()
  907. e()
  908. finish`[1:] {
  909. t.Error("Unexpected result:", testlogger.String(), err)
  910. return
  911. }
  912. }
  913. func TestStepDebuggingWithImport(t *testing.T) {
  914. var err error
  915. defer func() {
  916. testDebugger = nil
  917. }()
  918. testDebugger = NewECALDebugger(nil)
  919. il := &util.MemoryImportLocator{Files: make(map[string]string)}
  920. il.Files["foo/bar"] = `
  921. func myfunc(n) {
  922. if (n <= 1) {
  923. return n
  924. }
  925. n := n + 1
  926. return n
  927. }
  928. `
  929. code := `
  930. a := 1
  931. import "foo/bar" as foobar
  932. log("start")
  933. a := foobar.myfunc(a)
  934. log("finish: ", a)
  935. `
  936. if _, err = testDebugger.HandleInput("break ECALEvalTest:4"); err != nil {
  937. t.Error("Unexpected result:", err)
  938. return
  939. }
  940. if _, err = testDebugger.HandleInput("break foo/bar:4"); err != nil {
  941. t.Error("Unexpected result:", err)
  942. return
  943. }
  944. wg := &sync.WaitGroup{}
  945. wg.Add(1)
  946. go func() {
  947. _, err = UnitTestEvalAndASTAndImport(code, nil, "", il)
  948. if err != nil {
  949. t.Error(err)
  950. }
  951. wg.Done()
  952. }()
  953. tid := waitForThreadSuspension(t)
  954. if state := getDebuggerState(tid, t); state != `{
  955. "breakpoints": {
  956. "ECALEvalTest:4": true,
  957. "foo/bar:4": true
  958. },
  959. "code": "log(\"start\")",
  960. "threads": {
  961. "1": {
  962. "callStack": [],
  963. "error": null,
  964. "threadRunning": false
  965. }
  966. },
  967. "vs": {
  968. "a": 1,
  969. "foobar": {
  970. "myfunc": "ecal.function: myfunc (Line 2, Pos 1)"
  971. }
  972. }
  973. }` {
  974. t.Error("Unexpected state:", state)
  975. return
  976. }
  977. // Resume execution
  978. if _, err := testDebugger.HandleInput(fmt.Sprintf("cont %v resume", tid)); err != nil {
  979. t.Error("Unexpected result:", err)
  980. return
  981. }
  982. tid = waitForThreadSuspension(t)
  983. if state := getDebuggerState(tid, t); state != `{
  984. "breakpoints": {
  985. "ECALEvalTest:4": true,
  986. "foo/bar:4": true
  987. },
  988. "code": "return n",
  989. "threads": {
  990. "1": {
  991. "callStack": [
  992. "myfunc(a) (ECALEvalTest:5)"
  993. ],
  994. "error": null,
  995. "threadRunning": false
  996. }
  997. },
  998. "vs": {
  999. "n": 1
  1000. }
  1001. }` {
  1002. t.Error("Unexpected state:", state)
  1003. return
  1004. }
  1005. // Continue until the end
  1006. if _, err := testDebugger.HandleInput(fmt.Sprintf("cont %v Resume", tid)); err != nil {
  1007. t.Error("Unexpected result:", err)
  1008. return
  1009. }
  1010. wg.Wait()
  1011. if err != nil || testlogger.String() != `
  1012. start
  1013. finish: 1`[1:] {
  1014. t.Error("Unexpected result:", testlogger.String(), err)
  1015. return
  1016. }
  1017. }
  1018. func getDebuggerState(tid uint64, t *testing.T) string {
  1019. out, err := testDebugger.HandleInput(fmt.Sprintf("status"))
  1020. if err != nil {
  1021. t.Error(err)
  1022. return ""
  1023. }
  1024. outMap := out.(map[string]interface{})
  1025. out, err = testDebugger.HandleInput(fmt.Sprintf("describe %v", tid))
  1026. if err != nil {
  1027. t.Error(err)
  1028. return ""
  1029. }
  1030. outMap2 := out.(map[string]interface{})
  1031. outMap["vs"] = outMap2["vs"]
  1032. outMap["code"] = outMap2["code"]
  1033. delete(outMap, "breakonstart")
  1034. delete(outMap, "sources")
  1035. outBytes, _ := json.MarshalIndent(outMap, "", " ")
  1036. return string(outBytes)
  1037. }
  1038. func TestInjectAndExtractDebugging(t *testing.T) {
  1039. var err error
  1040. defer func() {
  1041. testDebugger = nil
  1042. }()
  1043. vs := scope.NewScope(scope.GlobalScope)
  1044. testDebugger = NewECALDebugger(vs)
  1045. if _, err = testDebugger.HandleInput("break ECALEvalTest:5"); err != nil {
  1046. t.Error("Unexpected result:", err)
  1047. return
  1048. }
  1049. wg := &sync.WaitGroup{}
  1050. wg.Add(1)
  1051. go func() {
  1052. _, err = UnitTestEval(`
  1053. b := 49
  1054. func myfunc() {
  1055. a := 56
  1056. log("test2 a=", a)
  1057. }
  1058. log("test1")
  1059. myfunc()
  1060. log("test3 b=", b)
  1061. `, vs)
  1062. if err != nil {
  1063. t.Error(err)
  1064. }
  1065. wg.Done()
  1066. }()
  1067. tid := waitForThreadSuspension(t)
  1068. out, err := testDebugger.HandleInput(fmt.Sprintf("status"))
  1069. outBytes, _ := json.MarshalIndent(out, "", " ")
  1070. outString := string(outBytes)
  1071. if err != nil || outString != `{
  1072. "breakonstart": false,
  1073. "breakpoints": {
  1074. "ECALEvalTest:5": true
  1075. },
  1076. "sources": [
  1077. "ECALEvalTest"
  1078. ],
  1079. "threads": {
  1080. "1": {
  1081. "callStack": [
  1082. "myfunc() (ECALEvalTest:8)"
  1083. ],
  1084. "error": null,
  1085. "threadRunning": false
  1086. }
  1087. }
  1088. }` {
  1089. t.Error("Unexpected result:", outString, err)
  1090. return
  1091. }
  1092. out, err = testDebugger.HandleInput(fmt.Sprintf("describe %v", tid))
  1093. outBytes, _ = json.MarshalIndent(out, "", " ")
  1094. outString = string(outBytes)
  1095. if err != nil || outString != `{
  1096. "callStack": [
  1097. "myfunc() (ECALEvalTest:8)"
  1098. ],
  1099. "callStackNode": [
  1100. {
  1101. "allowescapes": false,
  1102. "children": [
  1103. {
  1104. "name": "funccall"
  1105. }
  1106. ],
  1107. "id": 7,
  1108. "identifier": true,
  1109. "line": 8,
  1110. "linepos": 1,
  1111. "name": "identifier",
  1112. "pos": 69,
  1113. "source": "ECALEvalTest",
  1114. "value": "myfunc"
  1115. }
  1116. ],
  1117. "callStackVsSnapshot": [
  1118. {
  1119. "b": 49,
  1120. "myfunc": "ecal.function: myfunc (Line 3, Pos 1)"
  1121. }
  1122. ],
  1123. "callStackVsSnapshotGlobal": [
  1124. {
  1125. "b": 49,
  1126. "myfunc": "ecal.function: myfunc (Line 3, Pos 1)"
  1127. }
  1128. ],
  1129. "code": "log(\"test2 a=\", a)",
  1130. "error": null,
  1131. "node": {
  1132. "allowescapes": false,
  1133. "children": [
  1134. {
  1135. "children": [
  1136. {
  1137. "allowescapes": true,
  1138. "id": 5,
  1139. "identifier": false,
  1140. "line": 5,
  1141. "linepos": 6,
  1142. "name": "string",
  1143. "pos": 39,
  1144. "source": "ECALEvalTest",
  1145. "value": "test2 a="
  1146. },
  1147. {
  1148. "allowescapes": false,
  1149. "id": 7,
  1150. "identifier": true,
  1151. "line": 5,
  1152. "linepos": 18,
  1153. "name": "identifier",
  1154. "pos": 51,
  1155. "source": "ECALEvalTest",
  1156. "value": "a"
  1157. }
  1158. ],
  1159. "name": "funccall"
  1160. }
  1161. ],
  1162. "id": 7,
  1163. "identifier": true,
  1164. "line": 5,
  1165. "linepos": 2,
  1166. "name": "identifier",
  1167. "pos": 35,
  1168. "source": "ECALEvalTest",
  1169. "value": "log"
  1170. },
  1171. "threadRunning": false,
  1172. "vs": {
  1173. "a": 56
  1174. },
  1175. "vsGlobal": {
  1176. "b": 49,
  1177. "myfunc": "ecal.function: myfunc (Line 3, Pos 1)"
  1178. }
  1179. }` {
  1180. t.Error("Unexpected result:", outString, err)
  1181. return
  1182. }
  1183. if _, err := testDebugger.HandleInput(fmt.Sprintf("extract %v a foo", tid)); err != nil {
  1184. t.Error("Unexpected result:", err)
  1185. return
  1186. }
  1187. if _, err := testDebugger.HandleInput(fmt.Sprintf("inject %v a x := b + 1; x", tid)); err != nil {
  1188. t.Error("Unexpected result:", err)
  1189. return
  1190. }
  1191. // Continue until the end
  1192. if _, err := testDebugger.HandleInput(fmt.Sprintf("cont %v Resume", tid)); err != nil {
  1193. t.Error("Unexpected result:", err)
  1194. return
  1195. }
  1196. wg.Wait()
  1197. if vs.String() != `
  1198. GlobalScope {
  1199. b (float64) : 49
  1200. foo (float64) : 56
  1201. myfunc (*interpreter.function) : ecal.function: myfunc (Line 3, Pos 1)
  1202. }`[1:] {
  1203. t.Error("Unexpected result:", vs.String(), err)
  1204. return
  1205. }
  1206. if testlogger.String() != `
  1207. test1
  1208. test2 a=50
  1209. test3 b=49`[1:] {
  1210. t.Error("Unexpected result:", testlogger.String(), err)
  1211. return
  1212. }
  1213. }
  1214. func TestSimpleStacktrace(t *testing.T) {
  1215. res, err := UnitTestEval(`
  1216. func a() {
  1217. b()
  1218. }
  1219. func b() {
  1220. c()
  1221. }
  1222. func c() {
  1223. raise("testerror")
  1224. }
  1225. a()
  1226. `, nil)
  1227. if err == nil {
  1228. t.Error("Unexpected result: ", res, err)
  1229. return
  1230. }
  1231. ss := err.(util.TraceableRuntimeError)
  1232. if out := fmt.Sprintf("%v\n %v", err.Error(), strings.Join(ss.GetTraceString(), "\n ")); out != `
  1233. ECAL error in ECALTestRuntime (ECALEvalTest): testerror () (Line:9 Pos:2)
  1234. raise("testerror") (ECALEvalTest:9)
  1235. c() (ECALEvalTest:6)
  1236. b() (ECALEvalTest:3)
  1237. a() (ECALEvalTest:11)`[1:] {
  1238. t.Error("Unexpected output:", out)
  1239. return
  1240. }
  1241. }
  1242. func TestDebugDocstrings(t *testing.T) {
  1243. for k, v := range DebugCommandsMap {
  1244. if res := v.DocString(); res == "" {
  1245. t.Error("Docstring missing for ", k)
  1246. return
  1247. }
  1248. }
  1249. }
  1250. func TestDebuggingErrorInput(t *testing.T) {
  1251. var err error
  1252. defer func() {
  1253. testDebugger = nil
  1254. }()
  1255. vs := scope.NewScope(scope.GlobalScope)
  1256. testDebugger = NewECALDebugger(vs)
  1257. if _, err = testDebugger.HandleInput("uuu"); err.Error() != `Unknown command: uuu` {
  1258. t.Error("Unexpected result:", err)
  1259. return
  1260. }
  1261. if _, err = testDebugger.HandleInput("break"); err.Error() != `Need a break target (<source>:<line>) as first parameter` {
  1262. t.Error("Unexpected result:", err)
  1263. return
  1264. }
  1265. if _, err = testDebugger.HandleInput("break foo"); err.Error() != `Invalid break target - should be <source>:<line>` {
  1266. t.Error("Unexpected result:", err)
  1267. return
  1268. }
  1269. if _, err = testDebugger.HandleInput("rmbreak"); err.Error() != `Need a break target (<source>[:<line>]) as first parameter` {
  1270. t.Error("Unexpected result:", err)
  1271. return
  1272. }
  1273. if _, err = testDebugger.HandleInput("disablebreak"); err.Error() != `Need a break target (<source>:<line>) as first parameter` {
  1274. t.Error("Unexpected result:", err)
  1275. return
  1276. }
  1277. if _, err = testDebugger.HandleInput("disablebreak foo"); err.Error() != `Invalid break target - should be <source>:<line>` {
  1278. t.Error("Unexpected result:", err)
  1279. return
  1280. }
  1281. if _, err = testDebugger.HandleInput("break ECALEvalTest:3"); err != nil {
  1282. t.Error("Unexpected result:", err)
  1283. return
  1284. }
  1285. wg := &sync.WaitGroup{}
  1286. wg.Add(1)
  1287. go func() {
  1288. _, err = UnitTestEval(`
  1289. a:=1
  1290. log("test1")
  1291. log("test2")
  1292. log("test3")
  1293. `, vs)
  1294. if err != nil {
  1295. t.Error(err)
  1296. }
  1297. wg.Done()
  1298. }()
  1299. tid := waitForThreadSuspension(t)
  1300. out, err := testDebugger.HandleInput(fmt.Sprintf("status"))
  1301. outBytes, _ := json.MarshalIndent(out, "", " ")
  1302. outString := string(outBytes)
  1303. if err != nil || outString != `{
  1304. "breakonstart": false,
  1305. "breakpoints": {
  1306. "ECALEvalTest:3": true
  1307. },
  1308. "sources": [
  1309. "ECALEvalTest"
  1310. ],
  1311. "threads": {
  1312. "1": {
  1313. "callStack": [],
  1314. "error": null,
  1315. "threadRunning": false
  1316. }
  1317. }
  1318. }` {
  1319. t.Error("Unexpected result:", outString, err)
  1320. return
  1321. }
  1322. if _, err = testDebugger.HandleInput(fmt.Sprintf("extract %v foo foo", tid)); err.Error() != `No such value foo` {
  1323. t.Error("Unexpected result:", err)
  1324. return
  1325. }
  1326. }
  1327. func TestDebuggingErrorInput2(t *testing.T) {
  1328. var err error
  1329. tid := 1
  1330. defer func() {
  1331. testDebugger = nil
  1332. }()
  1333. vs := scope.NewScope(scope.GlobalScope)
  1334. testDebugger = NewECALDebugger(vs)
  1335. if _, err = testDebugger.HandleInput("cont foo"); err.Error() != `Need a thread ID and a command Resume, StepIn, StepOver or StepOut` {
  1336. t.Error("Unexpected result:", err)
  1337. return
  1338. }
  1339. if _, err = testDebugger.HandleInput("cont foo bar"); err.Error() != `Parameter 1 should be a number` {
  1340. t.Error("Unexpected result:", err)
  1341. return
  1342. }
  1343. if _, err = testDebugger.HandleInput("cont 99 bar"); err.Error() != `Invalid command bar - must be resume, stepin, stepover or stepout` {
  1344. t.Error("Unexpected result:", err)
  1345. return
  1346. }
  1347. if _, err = testDebugger.HandleInput("describe"); err.Error() != `Need a thread ID` {
  1348. t.Error("Unexpected result:", err)
  1349. return
  1350. }
  1351. if _, err = testDebugger.HandleInput(fmt.Sprintf("extract %v foo", tid)); err.Error() != `Need a thread ID, a variable name and a destination variable name` {
  1352. t.Error("Unexpected result:", err)
  1353. return
  1354. }
  1355. if _, err = testDebugger.HandleInput(fmt.Sprintf("extract %v _foo foo", tid)); err.Error() != `Variable names may only contain [a-zA-Z] and [a-zA-Z0-9] from the second character` {
  1356. t.Error("Unexpected result:", err)
  1357. return
  1358. }
  1359. if _, err = testDebugger.HandleInput(fmt.Sprintf("inject %v", tid)); err.Error() != `Need a thread ID, a variable name and an expression` {
  1360. t.Error("Unexpected result:", err)
  1361. return
  1362. }
  1363. testDebugger.(*ecalDebugger).globalScope = nil
  1364. if _, err = testDebugger.HandleInput(fmt.Sprintf("extract %v foo foo", tid)); err.Error() != `Cannot access global scope` {
  1365. t.Error("Unexpected result:", err)
  1366. return
  1367. }
  1368. if _, err = testDebugger.HandleInput(fmt.Sprintf("inject %v foo foo", tid)); err.Error() != `Cannot access global scope` {
  1369. t.Error("Unexpected result:", err)
  1370. return
  1371. }
  1372. }