error-handling.tap.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. 'use strict';
  2. var test = require('tap').test
  3. , cls = require('../context.js')
  4. , domain = require('domain')
  5. ;
  6. test("continuation-local storage glue with a throw in the continuation chain",
  7. function (t) {
  8. var namespace = cls.createNamespace('test');
  9. namespace.run(function () {
  10. var d = domain.create();
  11. namespace.set('outer', true);
  12. namespace.bindEmitter(d);
  13. d.on('error', function (blerg) {
  14. t.equal(blerg.message, "explicitly nonlocal exit", "got the expected exception");
  15. t.ok(namespace.get('outer'), "outer context is still active");
  16. t.notOk(namespace.get('inner'), "inner context should have been exited by throw");
  17. t.equal(namespace._set.length, 1, "should be back to outer state");
  18. cls.destroyNamespace('test');
  19. t.end();
  20. });
  21. // tap is only trying to help
  22. process.nextTick(d.bind(function () {
  23. t.ok(namespace.get('outer'), "outer mutation worked");
  24. t.notOk(namespace.get('inner'), "inner mutation hasn't happened yet");
  25. namespace.run(function () {
  26. namespace.set('inner', true);
  27. throw new Error("explicitly nonlocal exit");
  28. });
  29. }));
  30. });
  31. });
  32. test("synchronous throw attaches the context", function (t) {
  33. t.plan(3);
  34. var namespace = cls.createNamespace('cls@synchronous');
  35. namespace.run(function () {
  36. namespace.set('value', 'transaction clear');
  37. try {
  38. namespace.run(function () {
  39. namespace.set('value', 'transaction set');
  40. throw new Error('cls@synchronous explosion');
  41. });
  42. }
  43. catch (e) {
  44. t.ok(namespace.fromException(e), "context was attached to error");
  45. t.equal(namespace.fromException(e)['value'], 'transaction set',
  46. "found the inner value");
  47. }
  48. t.equal(namespace.get('value'), 'transaction clear', "everything was reset");
  49. });
  50. cls.destroyNamespace('cls@synchronous');
  51. });
  52. test("synchronous throw checks if error exists", function (t) {
  53. t.plan(2);
  54. var namespace = cls.createNamespace('cls@synchronous-null-error');
  55. namespace.run(function () {
  56. namespace.set('value', 'transaction clear');
  57. try {
  58. namespace.run(function () {
  59. namespace.set('value', 'transaction set');
  60. throw null;
  61. });
  62. }
  63. catch (e) {
  64. // as we had a null error, cls couldn't set the new inner value
  65. t.equal(namespace.get('value'), 'transaction clear', 'from outer value');
  66. }
  67. t.equal(namespace.get('value'), 'transaction clear', "everything was reset");
  68. });
  69. cls.destroyNamespace('cls@synchronous-null-error');
  70. });
  71. test("throw in process.nextTick attaches the context", function (t) {
  72. t.plan(3);
  73. var namespace = cls.createNamespace('cls@nexttick');
  74. var d = domain.create();
  75. namespace.bindEmitter(d);
  76. d.on('error', function (e) {
  77. t.ok(namespace.fromException(e), "context was attached to error");
  78. t.equal(namespace.fromException(e)['value'], 'transaction set',
  79. "found the inner value");
  80. cls.destroyNamespace('cls@nexttick');
  81. });
  82. namespace.run(function () {
  83. namespace.set('value', 'transaction clear');
  84. // tap is only trying to help
  85. process.nextTick(d.bind(function () {
  86. namespace.run(function () {
  87. namespace.set('value', 'transaction set');
  88. throw new Error("cls@nexttick explosion");
  89. });
  90. }));
  91. t.equal(namespace.get('value'), 'transaction clear', "everything was reset");
  92. });
  93. });
  94. test("throw in setTimeout attaches the context", function (t) {
  95. t.plan(3);
  96. var namespace = cls.createNamespace('cls@setTimeout');
  97. var d = domain.create();
  98. namespace.bindEmitter(d);
  99. d.on('error', function (e) {
  100. t.ok(namespace.fromException(e), "context was attached to error");
  101. t.equal(namespace.fromException(e)['value'], 'transaction set',
  102. "found the inner value");
  103. cls.destroyNamespace('cls@setTimeout');
  104. });
  105. namespace.run(function () {
  106. namespace.set('value', 'transaction clear');
  107. // tap is only trying to help
  108. setTimeout(d.bind(function () {
  109. namespace.run(function () {
  110. namespace.set('value', 'transaction set');
  111. throw new Error("cls@setTimeout explosion");
  112. });
  113. }));
  114. t.equal(namespace.get('value'), 'transaction clear', "everything was reset");
  115. });
  116. });