debug_test.go 31 KB

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