Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

569 lines
9.5 KiB

  1. /*
  2. * COMMAND LINE: -Ox -GX
  3. */
  4. /*
  5. Copyright (c) 1997 Microsoft Corporation
  6. Module Name:
  7. EhThrow.cxx
  8. Abstract:
  9. Tests some throw and rethrow situations (mostly CRT a test)
  10. Author:
  11. Louis Lafreniere (louisl) 1997
  12. */
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #define FALSE 0
  16. #define TRUE 1
  17. #define NO_CTOR_THROW 1
  18. #define NO_DTOR_THROW 2
  19. int Object[100];
  20. int CurrentObjectNumber, Test;
  21. int MaxTest = 10;
  22. int MaxObjectCount = 1;
  23. int Fail;
  24. void FAIL(int i)
  25. {
  26. printf("FAILED on %d\n", i);
  27. Fail++;
  28. }
  29. void dealloc(int i, int no_throw)
  30. {
  31. /* Make sure i is valid, and object exists */
  32. if(i<0 || i>=MaxObjectCount || !Object[i])
  33. FAIL(i);
  34. Object[i] = 0;
  35. }
  36. void alloc(int i, int no_throw)
  37. {
  38. if(CurrentObjectNumber > MaxObjectCount)
  39. MaxObjectCount = CurrentObjectNumber;
  40. /* Object already exists? */
  41. if(Object[i]) FAIL(i);
  42. Object[i] = 1;
  43. }
  44. class B
  45. {
  46. public:
  47. int i;
  48. int flag;
  49. B();
  50. B(int);
  51. B(const B &b);
  52. ~B();
  53. };
  54. B::B()
  55. {
  56. i = CurrentObjectNumber++;
  57. printf("B ctor. i = %d\n", i);
  58. alloc(i, FALSE);
  59. }
  60. B::B(int f)
  61. {
  62. i = CurrentObjectNumber++;
  63. flag = f;
  64. printf("B ctor. i = %d\n", i);
  65. alloc(i, flag==NO_CTOR_THROW);
  66. }
  67. B::B(const B &b)
  68. {
  69. i = CurrentObjectNumber++;
  70. printf("B copy ctor. i = %d\n", i);
  71. alloc(i, FALSE);
  72. }
  73. B::~B()
  74. {
  75. printf("B dtor. i = %d\n", i);
  76. dealloc(i, flag==NO_DTOR_THROW);
  77. }
  78. class A
  79. {
  80. public:
  81. int i;
  82. A();
  83. A(int)
  84. {
  85. i = CurrentObjectNumber++;
  86. printf("A(int) ctor. i = %d\n", i);
  87. alloc(i, FALSE);
  88. }
  89. A operator+(A a);
  90. A(const A &a)
  91. {
  92. /* Try objects in ctor */
  93. B b1 = NO_DTOR_THROW, b2 = NO_DTOR_THROW;
  94. i = CurrentObjectNumber++;
  95. printf("A copy ctor. i = %d\n", i);
  96. alloc(i, FALSE);
  97. }
  98. ~A(){
  99. /* Try objects in dtor */
  100. B b1 = NO_CTOR_THROW, b2 = NO_CTOR_THROW;
  101. printf("A dtor. i = %d\n", i);
  102. dealloc(i, FALSE);
  103. };
  104. };
  105. A::A()
  106. {
  107. i=CurrentObjectNumber++;
  108. printf("A ctor. i = %d\n", i);
  109. alloc(i, FALSE);
  110. }
  111. A A::operator+(A a)
  112. {
  113. printf("A%d + A%d\n", i, a.i);
  114. return A();
  115. }
  116. void Throwa(A a)
  117. {
  118. printf("Throwing\n");
  119. throw a;
  120. }
  121. void bar()
  122. {
  123. A a;
  124. Throwa(a);
  125. }
  126. void foobar()
  127. {
  128. B b;
  129. bar();
  130. }
  131. // Somehow, inlining this causes different unwinding order..
  132. void Rethrow2()
  133. {
  134. A a;
  135. printf("Rethrowing\n");
  136. throw;
  137. }
  138. #pragma inline_depth(0)
  139. void Rethrow()
  140. {
  141. Rethrow2();
  142. }
  143. #pragma inline_depth()
  144. void foobar2()
  145. {
  146. B b;
  147. try{
  148. A a;
  149. bar();
  150. }catch(A a){
  151. printf("In catch;\n");
  152. Rethrow();
  153. }
  154. }
  155. void foobar3()
  156. {
  157. B b;
  158. try{
  159. A a;
  160. bar();
  161. }catch(A a){
  162. printf("In catch\n");
  163. A a2;
  164. printf("Throwing new a\n");
  165. throw a2;
  166. }
  167. }
  168. void foobar4()
  169. {
  170. B b;
  171. try{
  172. B b;
  173. try{
  174. A a1, a2;
  175. try {
  176. A a1, a2;
  177. foobar2();
  178. }catch(A a){
  179. printf("In catch #1\n");
  180. B b;
  181. printf("Rethrowing\n");
  182. throw;
  183. }
  184. }catch(A &a){
  185. printf("In catch #2\n");
  186. A a2;
  187. printf("Throwing new a\n");
  188. throw a;
  189. }
  190. }catch(A a){
  191. printf("In catch #3\n");
  192. B b;
  193. printf("Rethrowing\n");
  194. throw;
  195. }
  196. }
  197. void throw_B_2()
  198. {
  199. B b;
  200. printf("Throwing a new b\n");
  201. throw b;
  202. }
  203. #pragma inline_depth(0)
  204. void throw_B()
  205. {
  206. throw_B_2();
  207. }
  208. #pragma inline_depth()
  209. void foobar5()
  210. {
  211. try {
  212. B b1;
  213. try {
  214. B b2;
  215. try {
  216. B b3;
  217. foobar();
  218. }catch(B b){
  219. printf("In catch #1\n");
  220. FAIL(-1);
  221. }
  222. FAIL(-1);
  223. }catch(A a){
  224. A a2;
  225. printf("In catch #2\n");
  226. throw_B();
  227. }
  228. FAIL(-1);
  229. }catch(B b){
  230. printf("In catch #3\n");
  231. printf("Throwing a new a\n");
  232. throw A();
  233. }
  234. FAIL(-1);
  235. }
  236. /* Simple throw with unwinds */
  237. void test1()
  238. {
  239. A a;
  240. foobar();
  241. }
  242. /* Throw followed by a rethrow */
  243. void test2()
  244. {
  245. A a;
  246. foobar2();
  247. }
  248. /* Throw followed by a new throw */
  249. void test3()
  250. {
  251. A a;
  252. foobar3();
  253. }
  254. /* Nested trys with rethrow/throw/rethrow */
  255. void test4()
  256. {
  257. A a;
  258. foobar4();
  259. }
  260. /* Makes sure a new throw skips appropriate unwound frames. */
  261. void test5()
  262. {
  263. A a;
  264. foobar5();
  265. }
  266. // Tests 3 level of new throw
  267. void test6()
  268. {
  269. try{
  270. B b1;
  271. try{
  272. B b2;
  273. try{
  274. B b3;
  275. printf("Throwing a b\n");
  276. throw(b3);
  277. }catch(B b){
  278. B b4;
  279. printf("In catch #1\n");
  280. printf("Throwing a new b\n");
  281. throw(b4);
  282. }
  283. FAIL(-1);
  284. }catch(B b){
  285. B b5;
  286. printf("In catch #2\n");
  287. printf("Throwing a new b\n");
  288. throw(b5);
  289. }
  290. FAIL(-1);
  291. }catch(B b){
  292. A a1;
  293. printf("In catch #3\n");
  294. printf("Throwing a new a\n");
  295. throw(a1);
  296. }
  297. FAIL(-1);
  298. }
  299. // Testing try/catch inside a catch
  300. void test7()
  301. {
  302. B b1;
  303. try{
  304. B b2;
  305. try{
  306. B b3;
  307. printf("Throwing a b\n");
  308. throw(B());
  309. }catch(B b){
  310. B b4;
  311. printf("In catch #1\n");
  312. try{
  313. B b5;
  314. printf("Rethrowing b\n");
  315. throw;
  316. }catch(B b){
  317. B b5;
  318. printf("In catch #1 of catch#1\n");
  319. printf("Rethrowing b\n");
  320. throw;
  321. }
  322. }
  323. }catch(B b){
  324. B b6;
  325. printf("In catch #2\n");
  326. printf("Throwing a new A\n");
  327. throw(A());
  328. }
  329. }
  330. void ThrowB()
  331. {
  332. B b;
  333. throw(B());
  334. }
  335. void bar8()
  336. {
  337. try{
  338. B b5;
  339. printf("Rethrowing b\n");
  340. Rethrow();
  341. }catch(B b){
  342. B b5;
  343. printf("In catch #1 of catch#1\n");
  344. printf("Rethrowing b\n");
  345. Rethrow();
  346. }
  347. }
  348. void foo8()
  349. {
  350. B b;
  351. try{
  352. B b3;
  353. printf("Throwing a b\n");
  354. ThrowB();
  355. }catch(B b){
  356. B b4;
  357. printf("In catch #1\n");
  358. bar8();
  359. }
  360. }
  361. // Testing call to try/catch function inside a catch
  362. void test8()
  363. {
  364. B b1;
  365. try{
  366. B b2;
  367. foo8();
  368. }catch(B b){
  369. B b6;
  370. printf("In catch #2\n");
  371. printf("Throwing a new A\n");
  372. throw(A());
  373. }
  374. }
  375. void foo9()
  376. {
  377. try {
  378. puts("Rethrow");
  379. throw;
  380. }catch(...){
  381. puts("In catch #2");
  382. }
  383. }
  384. void test9()
  385. {
  386. try{
  387. B b;
  388. puts("Throwing B");
  389. throw b;
  390. }catch(...){
  391. puts("In catch #1");
  392. foo9();
  393. }
  394. puts("End of test9, throwing a A");
  395. throw A();
  396. }
  397. void foo10()
  398. {
  399. try {
  400. puts("Throwing a new B()");
  401. throw B();
  402. }catch(...){
  403. puts("In catch #2");
  404. }
  405. }
  406. void test10()
  407. {
  408. try{
  409. B b;
  410. puts("Throwing B");
  411. throw b;
  412. }catch(...){
  413. puts("In catch #1");
  414. foo10();
  415. }
  416. puts("End of test10, throwing a A");
  417. throw A();
  418. }
  419. void main()
  420. {
  421. int i;
  422. /* Call test(), with a different ctor/dtor throwing each time */
  423. for(Test = 1; Test <= 10; Test++) {
  424. CurrentObjectNumber = 0;
  425. printf("\nTest #%d\n", Test);
  426. try {
  427. switch(Test){
  428. case 1:
  429. test1();
  430. break;
  431. case 2:
  432. test2();
  433. break;
  434. case 3:
  435. test3();
  436. break;
  437. case 4:
  438. test4();
  439. break;
  440. case 5:
  441. test5();
  442. break;
  443. case 6:
  444. test6();
  445. break;
  446. case 7:
  447. #if !defined(_M_IA64)
  448. test7();
  449. #else
  450. continue;
  451. #endif
  452. break;
  453. case 8:
  454. test8();
  455. break;
  456. case 9:
  457. #if !defined(_M_IA64)
  458. test9();
  459. #else
  460. continue;
  461. #endif
  462. break;
  463. case 10:
  464. test10();
  465. break;
  466. }
  467. FAIL(-1);
  468. }catch(A a){
  469. printf("In main's catch\n");
  470. }catch(...){
  471. FAIL(-1);
  472. }
  473. /* Any objects which didn't get dtor'd? */
  474. for(i = 0; i < MaxObjectCount; i++) {
  475. if(Object[i]) {
  476. FAIL(i);
  477. Object[i] = 0;
  478. }
  479. }
  480. printf("\n");
  481. }
  482. printf("\n");
  483. if(Fail)
  484. printf("FAILED %d tests\n", Fail);
  485. else
  486. printf("Passed\n");
  487. }