From 77a06573a9ac854ef0e75b021f39625a7a6dc3ff Mon Sep 17 00:00:00 2001 From: Alena Laskavaia Date: Mon, 16 Apr 2012 21:56:57 -0400 Subject: [PATCH 01/13] Bug 316076 - fixed f.p. when using gcc annotation about no return --- .../cdt/codan/core/cxx/CxxAstUtils.java | 8 +++++ .../cdt/codan/core/cxx/CxxAstUtilsTest.java | 33 +++++++++++++++++++ .../internal/checkers/ReturnCheckerTest.java | 12 +++++++ 3 files changed, 53 insertions(+) diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java index 4f4dc1560f0..6bb0baf6241 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java @@ -406,6 +406,14 @@ public final class CxxAstUtils { if (!(expression instanceof IASTFunctionCallExpression)) return false; IASTExpression functionNameExpression = ((IASTFunctionCallExpression) expression).getFunctionNameExpression(); + if (functionNameExpression instanceof IASTIdExpression) { + IASTName name = ((IASTIdExpression)functionNameExpression).getName(); + + IBinding binding = name.resolveBinding(); + if (binding!=null && binding instanceof IFunction && ((IFunction)binding).isNoReturn()) { + return true; + } + } return functionNameExpression.getRawSignature().equals("exit"); //$NON-NLS-1$ } } diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtilsTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtilsTest.java index 7e4c036ca05..9d44246b2b2 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtilsTest.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtilsTest.java @@ -100,4 +100,37 @@ public class CxxAstUtilsTest extends CodanFastCxxAstTestCase { assertTrue((Boolean) result[0]); assertFalse((Boolean) result[1]); } + + //void f() __attribute__((noreturn)); + // + //int test() { + // a(); + // f(); + // exit(0); + //} + public void testExitStatement() throws IOException { + String code = getAboveComment(); + IASTTranslationUnit tu = parse(code); + final Object result[] = new Object[4]; + ASTVisitor astVisitor = new ASTVisitor() { + int i; + { + shouldVisitStatements = true; + } + + @Override + public int visit(IASTStatement stmt) { + boolean check = CxxAstUtils.isExitStatement(stmt); + result[i] = check; + i++; + return PROCESS_CONTINUE; + } + }; + tu.accept(astVisitor); + assertNotNull("Stmt not found", result[0]); //$NON-NLS-1$ + assertFalse((Boolean) result[0]); // compound body + assertFalse((Boolean) result[1]); + assertTrue((Boolean) result[2]); + assertTrue((Boolean) result[3]); + } } diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java index 95519bf9fb6..75584462eb4 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java @@ -298,4 +298,16 @@ public class ReturnCheckerTest extends CheckerTestCase { loadCodeAndRunCpp(getAboveComment()); checkNoErrors(); } + + +//void f() __attribute__((noreturn)); +// +//int test() { +// f(); +//} + + public void testNoReturn() { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } } \ No newline at end of file From 74138d21f55778a2d1fe1ce745ba2736ebbea57a Mon Sep 17 00:00:00 2001 From: Mikhail Khodjaiants Date: Mon, 16 Apr 2012 16:56:17 -0400 Subject: [PATCH 02/13] Bug 361934 - Provide timeout for gdb commands Change-Id: Id51a138411e49f7157858379f8aa09a59a8e4f78 Reviewed-on: https://git.eclipse.org/r/5523 Reviewed-by: Mikhail Khodjaiants IP-Clean: Mikhail Khodjaiants Tested-by: Mikhail Khodjaiants --- .../icons/full/wizban/advtosettings_wiz.png | Bin 0 -> 8548 bytes dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml | 9 + .../dsf/gdb/internal/ui/GdbStatusHandler.java | 66 +++ .../cdt/dsf/gdb/internal/ui/GdbUIPlugin.java | 31 + .../dsf/gdb/internal/ui/IGdbUIConstants.java | 28 + .../cdt/dsf/gdb/internal/ui/Messages.java | 29 + .../dsf/gdb/internal/ui/Messages.properties | 14 + .../preferences/GdbDebugPreferencePage.java | 536 +++++++++++++++++- .../preferences/MessagesForPreferences.java | 13 + .../MessagesForPreferences.properties | 14 + dsf-gdb/org.eclipse.cdt.dsf.gdb/.options | 1 + .../cdt/dsf/gdb/IGdbDebugConstants.java | 8 +- .../dsf/gdb/IGdbDebugPreferenceConstants.java | 30 +- .../internal/GdbPreferenceInitializer.java | 2 + .../cdt/dsf/gdb/internal/Messages.java | 32 ++ .../cdt/dsf/gdb/internal/Messages.properties | 15 + .../service/command/CustomTimeoutsMap.java | 79 +++ .../dsf/gdb/service/command/GDBControl.java | 124 ++++ .../gdb/service/command/GDBControl_7_0.java | 2 + .../command/GdbCommandTimeoutManager.java | 443 +++++++++++++++ .../mi/service/command/AbstractMIControl.java | 45 ++ .../tests/dsf/gdb/framework/BaseTestCase.java | 17 +- .../cdt/tests/dsf/gdb/tests/AllTests.java | 1 + .../dsf/gdb/tests/CommandTimeoutTest.java | 143 +++++ .../tests_6_6/CommandTimeoutTest_6_6.java | 26 + .../dsf/gdb/tests/tests_6_6/Suite_6_6.java | 3 +- .../gdb/tests/tests_6_6/Suite_Remote_6_6.java | 3 +- .../tests_6_7/CommandTimeoutTest_6_7.java | 26 + .../dsf/gdb/tests/tests_6_7/Suite_6_7.java | 3 +- .../gdb/tests/tests_6_7/Suite_Remote_6_7.java | 3 +- .../tests_6_8/CommandTimeoutTest_6_8.java | 26 + .../dsf/gdb/tests/tests_6_8/Suite_6_8.java | 3 +- .../gdb/tests/tests_6_8/Suite_Remote_6_8.java | 3 +- .../tests_7_0/CommandTimeoutTest_7_0.java | 26 + .../dsf/gdb/tests/tests_7_0/Suite_7_0.java | 3 +- .../gdb/tests/tests_7_0/Suite_Remote_7_0.java | 3 +- .../tests_7_1/CommandTimeoutTest_7_1.java | 26 + .../dsf/gdb/tests/tests_7_1/Suite_7_1.java | 3 +- .../gdb/tests/tests_7_1/Suite_Remote_7_1.java | 3 +- .../tests_7_2/CommandTimeoutTest_7_2.java | 26 + .../dsf/gdb/tests/tests_7_2/Suite_7_2.java | 3 +- .../gdb/tests/tests_7_2/Suite_Remote_7_2.java | 3 +- .../tests_7_3/CommandTimeoutTest_7_3.java | 26 + .../dsf/gdb/tests/tests_7_3/Suite_7_3.java | 3 +- .../gdb/tests/tests_7_3/Suite_Remote_7_3.java | 3 +- .../tests_7_4/CommandTimeoutTest_7_4.java | 26 + .../dsf/gdb/tests/tests_7_4/Suite_7_4.java | 3 +- .../gdb/tests/tests_7_4/Suite_Remote_7_4.java | 1 + 48 files changed, 1905 insertions(+), 31 deletions(-) create mode 100755 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/wizban/advtosettings_wiz.png create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbStatusHandler.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/IGdbUIConstants.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.properties create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.properties create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/CustomTimeoutsMap.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GdbCommandTimeoutManager.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/CommandTimeoutTest.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/CommandTimeoutTest_6_6.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/CommandTimeoutTest_6_7.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/CommandTimeoutTest_6_8.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/CommandTimeoutTest_7_0.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/CommandTimeoutTest_7_1.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/CommandTimeoutTest_7_2.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/CommandTimeoutTest_7_3.java create mode 100644 dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/CommandTimeoutTest_7_4.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/wizban/advtosettings_wiz.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/wizban/advtosettings_wiz.png new file mode 100755 index 0000000000000000000000000000000000000000..7229ca07fd35c5f8236ef2ddbb63c03fe67e29ab GIT binary patch literal 8548 zcmV-qA)DTbP)002S=1^@s6A3-Z300009a7bBm000XU z000XU0RWnu7ytkYO=&|zP*7-ZbZ>KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde00d`2O+f$vv5tKEQIh}w03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(` z>RI+y?e7jKeZ#YO-C7J*4bK~#9!?3{U!9o3bmznk03w^zNYQmIN3ln`0~3AEX) zAq1M1u}zEthp}gj-FSKyH(`hEuxBPFraiVNW};*0iNS79+Zab1+D&)kwwujv2GrQd z2y6t{Ab|u3g!ZLWQf+U`?cOtgysTGMLI?>8aNy2}jLdqOFPHC~d+xcvb8adAc{$;7 z^IZpQ5quFTi%YuSp1LOi(5lSMG7a=?K`0qWeTYhrT79np0-x$e?k-QPS6P^2e z3+vnW9LgF)PDDH-*v3fF7|Do$krRK%`F#R(>-~o%01a4LrLdjspX zpA8m`NKSzzEz7YHDJk$ywRyegVg2O;gIOcAED4a731tO}3Y472wPqC7%K!W~x2!m` z>zdi6>_En~X@oK3&4_9w{cE4Sa?s({km-cF|k`|=Y zNf%M%rhfLWz^aaneQ`Jkz9}&QtJaLDHX~}ykVZ42*$in0@mlQ{Zv?(R(~$1`ry<*j zltl24gQ1k71Mo!N+_kNld{7+*r*@(dqS0eBZcTsl@K7G;R^T7k=R1}~MRDSg;9aq- z(Zl=Lw0ApbO`;91W0Po2oM@6nqbwU`+bG9F`Gpy~?~fii>ZaD@0UT#Jj-{xGoSuJr z+hGmw-}xEff>LMSjVo82+tJ-oWVBjmc%;V2c#ZL~8pn?8x)<02gLlltJ%7CMXx<0~ zg|g&0FQmXxN>xPUErXi*-f-LfcK|r+zPQ}?Giytw0$N!_M$ym)s}aJs`>&meTiw0s zm}Lx|f_Nu#)=IT3$_PqiW?t`Y2_161{ZzUuv|!l;#-boLO_iCE>)-p>G2aMfrP?vm z@t)jKii#N2>Gyf>1g!NpT?2fir(9g?It;wtX)A8JS@sPbd-mv9btCXsZ1~Qzr*oV8 z9v?0VsOsOux`b94D@#M@NakU(t#tdIekH2 zg->3&f<&9;uN*wG{PFECeewC+m!BPPG{41$@0`?!{o@nEmJvEdUcc*C;8>Qbm>Kd> zGdGZ4f73N{yDPW+;U8Q&aP@^3;5ZhpZQa^qON@ud@4+5?+MToEcFVwrTHD@JJT3t~XPR*EhWl$khY zTE{2({*h#((?4HFOp8c&<&xwQ-#mEXTI6Ern7F5#i`~ zgRxqZDA7c*CP-m5!i0Jdk;`R?jp5t(Jjm9ayT8PS?|gIOb`L%|k`?GM21F(R9S2KL zX?WmFhcdIU?9&BR&SxL_`lqhF>V_*XrlXK0@4J(0#>Mv>9IN#kXd`GNWHT=HAVLIO z$HH@MY|Fy36t<;^;+T286)rh%39jp2^_-eDz|N=c+wk;g2`I^w*h$hAncR15)dk9t ziO)`DD<}SZ;vR3!XQiON`Pok{Upg>{obQm!IQX7}?>Z<2VXO&)gdj3Ri6+s4NuMCn zaCEGJWhorn!gVZ4IWKLtib}!9wnDDGbTx%+=Egf**8{%thECT~CBS(*eAJt^tn&G5 ze*MkQescM;`Ew{_UGiC%yzk+AHesAF)`%FXg^blBMjH{;MvSB#w>CnU7>fvQN>f zZu#;@uexT<`HRT=E`_X1!S}E&i)yn4X`~i1)`%$OGtB8Kuy|gD-p(BV@9F1Rw{jtU z-FfEscaqO$s0Rsy!!@GBkZ2+2yUd^6iLDeu%Xjp4RoHjr*s8z##l~$PzVO0Vj)!F_ zJlj&`(}r|{9@>_OhjmZvEW9T$fsuMppay1_IkUIO|GE2D{PCaP$4EUSF|cjVAw&$1Jo{3+Io|lEck!YB z^nDJERJrPsb6B=;EJel0h_m`S z=;_Gu+^#|HfBbp&4~=pAgHNMHSaw!703W$*F|iglzp$6xhliQnRpi&t?;=PHXY_Y5 zt258gSd*jU0ZC%Wx{9Lj(ox8;XwGbASIQs%i=W;%F9lUn>dghyBG}sCCt6BLB3)Wb zNrbG(sa@}lEb9-iyKFU?G>&RHbIo|O1*)&BKu<@O#0Zsgo@~ZttR8UfWlPaUSaN0` z02$Xq8)4OwGg!5FE=s|r=P$sRR&y(r^JHDcu7k%I9IoPfHifK9&U0}r#YIaN@vH6I zuD30fv8?I2yi)+Aw82jjDJNPwjgf-Lo71(NlUUWjrRObNTbUAcT9%?#Z}oJJW6@Ri z`Oz<*r@yO4;?|*&axC^poBn0gp9FuTkTAKuD$@BcNQ|MPpPH6s!u#9Gh>v`ofWOU~$T1*oax4r7Bh z@V$FC@tYTRbL+jEXe7ddxm_F{sd4C7l_=4Gpb)gy%qo}We(!+?mb{T4O0?u6EfsB~ zWQ5F2##twWb@{US^RR8z9=6~xvly!fEa>k-fc{w>RO&_x*u6-JLk9HP!@Ktslv04AtDI;5;4ot~7teKxl7vuea``+9^ZC_a zR`+(7>8n`(;gv&szH&y-ye;ok4)S$jSxTi_(m+v2j7i6PaNlFk^AC?c$7Scw=Tjee zKU!XERYqV=Pbc}T-?k=&N@2CG`|Iak;sYR)_WnI5+B_q{3y`3diE}qA>9ear4gdmC$pbn?9M!HFiBab3Rfu`5vuJWDZJZ4f6dRYDt~-V7-^@M5(=BhmoG4B|WXmQP=K z(cQljuwLAEV52r>ZLAGRVo(_eFI7R0jy0K+&0txI=UzETG4IpgU1?k3RKJ9R>(;K| zXOC^=iAD3ck-?On0_8b^O8~ED|zu~Lj`x&4A-+#}Z!$(`q zOQoO`Z9jFz%7x^8m!EFh!dSI|r4+V;Z~b^9o3^~d|GM*Ge8-|0L~MWcAf(rcW1VKS z4b3=ac4y~K-o@o)uzvZ(wwD-?iBO@_w$pd^x3@PhWS5h4XsIxHh&0QEb}T zkO^mg?b_w!eV2WM!#w+PhLwxw@ulmp;PT~XbHV&x>dk#?)w!B=XEo0Rt2RLuHAB8u5EMv!hXK__rK(xN1x;9Xq`)z&Syby2U*YN z2lsB`@NkuKF^`{dX*5IXjevS1VDIoSm2$_A)-7N0f^eLW_XZ*#Y0P&@O6gmaXukE2 zPyCjl(HeszH3o-kB-*qxIa!xI`vw^s9Y-m}p`&BegNUW`XY=figIEf-?>fMTzH%#H z{`Ng-vsApecZh{^yBVoA$hiv7R@}ew8J>A*KgE2Od^ST6#x#PEW)Kp`3A=}fYkzdr z2RHC8FDI9kcRscIP-WrT#dG=x9Lqu*Lm~#xwTWX*5JhZ%Wk0jZITp<8C5RH5Va#=x zUqDYso()gF$ap=V)(AOcb|-yZWzL@4O~H5h#M)(am9pIR;AS>#et~i^Pq~yw1nSLz z+Jsdd8zEmT{OFTctb0n*Ao<<0tT)!+7rbxFq2ZCwF6ixT#a&4&{&5_OIMLLDh-Y8i zi;hA*eDS$__|m0R$^|T?DEJw+?;fPLv%n4OSL4}=bLMq($+`0wuQvGp-H-Cj%LnKv z<>@Hpv6Mxv8BnV?TWd35+mXS+|N4o4^=Fl0Df-=qwezXNV|`1NoFwenGsrV9>|%I$oX)&QA?tBwZ<(tvTEbQDTa520YPAMickJV?ho0pAN4HQ9 z6FN$HO2r&XDe8?$P>p8D)`JJRa>a_TuV1xlpG*Y3?;@;I7yZ}Ybo&+Oopa;DzFzXa zM>bs@$EF#^jMo}e>jBLmB8p;)xeT^t(NWA2#Yuad7bS*_=aTh3@>!ou#wAG->ZwDo z)|)gM0b36qWMEGJpMB$oPi<(Y;*Dvi@23W(tu#F+NYjIeIq`9Gg7ec6h|EZ>!}>pd z=Hj!@UVhfB9{h|;#&hvJ2hVk|9UG$!K^POoNvpYPgAs#5Vc81Dw((qtjOXGyHX;y2 z5shZp?)@4;z>9-}xSsd(?|Yz!^3TKz(kcv@tZkT56OqD_R6d&cj!eK3 zK^rBB#>57l7-Z&Pr53idukXgQdV0uYT(W+KtnanKIgX8@mHeAN6j4}KD@Co1CX5oo zC?*IeDwsp+LCF5m5eE8u|LRY!zwUvlFWw&1PYm$elF+0aBvXn;TFKhU@#@sEYif-q z(HJAjL>e6%rGrGpCIvPlunrGL#ijrLPrhbi{pIuf=g?8i<9RJB%XluXYvb59wr#fq zQc2S++O#@|iO4*RV!|+@8Aena4TkE~#<~^D{_=*km;I*gM~t+T3^VDoroOnO#|)E@ zrUGWle*60d(MIXSU}CMJFi~-Alx`*}nlV^|BatUUml62X&9|NRBB@N=s$Pzwm?(ud7B=WA7dC(HL+gIrQ!X{8ftc!yMW%dq zqI2W~4qT@Fty_gXMjNFQO&n?~s7F?_nOKoFGBeF^Xf(D&q{j%>#4oG0QJ=o~w##?y zJ@6k(er`o2mnZLeEj>OOMdE!}wgIwW&BF4^Xl;m+7%hfo9Ma#@`SeFGUiIMOzTVN- z1HlPDpALp;z1>tt-QG7^lrgQ}EKZDygT!i#ht7C2R?&<)_@U9bE1hnJ5r~7p4TG>? zjG1M$$vw9H<+;Du`qHI`N5+>no8gk|*b}+;&mW|J{&EiQf0k-7^*1MBUbu&n8;35v7fgXrtmtt9mtZMysJ+ zjg2y=+8dry+WOd7T$FSghfWeZXf*sJiVGt2X{|G2Oy=UV&uCtF*1TVe$m57OKe_YK zt5?pieQ@O^vv}_5r^qyO4}atn*FK7+GE-hyA(B&wl9p)Ewgxo?l$uBiB2(w!w62lP zR+2PNFj1eJu0{l{P_aUch)P0jkB)}Uu|{l%r>lj%A*|u?*cB*T4ISvXV3`TX0=v~qc|_nEg}^$ zCN0kqPmDN%I3nUAI3i-(mOBlWZF@c<`Dq1E?XB3y@nB*ifJ%LinrdYevUKXeC(4vk zU>Z?6ZB0oc)>tEPj*La#(IBxRBk*RE`6q=HHk*}Zy-|sRu$V+i5v6(r%3_Q!DJUc2 zBH~DEvZLMFV$bT$X8de+3M?lhBDu+Dm8piJkV%V~sBu@P^j_^`q_mnG7>Kl3V@>TG zs>beMJ$CC_khfa#Fb&qNH!oQZ+|s(YW&iZfwLU0YDcez&<0@=NDa!(7wIWZ;0u)Lq zB@;h-E8*xcQtX|(fX?2v*!Bj7k8D2szPoPdJ3$|#PURgsI`dR2En{80{FcWitxFJ; z28jg~C1Q<)+CEg(nf=ws8%?8unO91$yyB7$$Lm_FEN^BmZrfz?XR>Vd2N+m5k`Efk z@=w6Ei3dnk9GiDg-ci8xYwjQ|j7u|^_eAE;@6S2gj56Qi{7=9}C}VLko$mW*NayUd6i8QzntN%C?w zHdv#PIC~l!_0lY+_tXYJXm=Rd#of4rmWV-htn#t=u*WDeEyux$t1 z%>a+R<~x07-zI`;Bx3Im#CxTt{ez)#g10*@=1d7&;zSl~9jy<2&9Yq2^|HB^f0|;* z(_Eyql?Caq_X<20sp(5o`8T@ggJw4;{9qTAZk z^r;|XrfO3s(x~2jJ*%Ct2qK*YG6)q=Z+U8+>sZ;hT2cJFwpajBY%GQ95TU{h%t2HN z<=86Adu*}N#@H#)g_@bknvSh9>OJ^>ZmdKbALyGYPynv2a=Zr@3z)BFaQd%nDNiY7 ey%%Bq{{aA{5cZ6Xhu{AI0000 + + + + diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbStatusHandler.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbStatusHandler.java new file mode 100644 index 00000000000..3bbd6396570 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbStatusHandler.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal.ui; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.debug.core.IStatusHandler; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +public class GdbStatusHandler implements IStatusHandler { + + /* (non-Javadoc) + * @see org.eclipse.debug.core.IStatusHandler#handleStatus(org.eclipse.core.runtime.IStatus, java.lang.Object) + */ + @Override + public Object handleStatus( final IStatus status, Object source ) throws CoreException { + Runnable runnable = null; + if ( status.getSeverity() == IStatus.ERROR ) { + runnable = new Runnable() { + + @Override + public void run() { + Shell parent = GdbUIPlugin.getActiveWorkbenchShell(); + if ( parent != null ) + MessageDialog.openError( parent, Messages.GdbStatusHandler_Error, status.getMessage() ); + } + }; + } + else if ( status.getSeverity() == IStatus.WARNING ) { + runnable = new Runnable() { + + @Override + public void run() { + Shell parent = GdbUIPlugin.getActiveWorkbenchShell(); + if ( parent != null ) + MessageDialog.openWarning( parent, Messages.GdbStatusHandler_Warning, status.getMessage() ); + } + }; + } + else if ( status.getSeverity() == IStatus.INFO ) { + runnable = new Runnable() { + + @Override + public void run() { + Shell parent = GdbUIPlugin.getActiveWorkbenchShell(); + if ( parent != null ) + MessageDialog.openInformation( parent, Messages.GdbStatusHandler_Information, status.getMessage() ); + } + }; + } + if ( runnable != null ) + Display.getDefault().asyncExec( runnable ); + return null; + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java index 2aedaeb95b0..3e9ed2919f2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java @@ -22,6 +22,9 @@ import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; @@ -227,4 +230,32 @@ public class GdbUIPlugin extends AbstractUIPlugin { } } + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeImageRegistry(org.eclipse.jface.resource.ImageRegistry) + */ + @Override + protected void initializeImageRegistry( ImageRegistry reg ) { + super.initializeImageRegistry( reg ); + declareImages( reg ); + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + + public static Image getImage( String key ) { + return getDefault().getImageRegistry().get( key ); + } + + private void declareImages( ImageRegistry reg ) { + reg.put( IGdbUIConstants.IMG_WIZBAN_ADVANCED_TIMEOUT_SETTINGS, + getImageDescriptor( "icons/full/wizban/advtosettings_wiz.png" ) ); //$NON-NLS-1$ + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/IGdbUIConstants.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/IGdbUIConstants.java new file mode 100644 index 00000000000..3a10e92f305 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/IGdbUIConstants.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal.ui; + +/** + * @noimplement This interface is not intended to be implemented by clients. + * + * @since 4.1 + */ +public interface IGdbUIConstants { + + /** + * Plug-in identifier (value "org.eclipse.cdt.dsf.gdb.ui"). + */ + public static final String PLUGIN_ID = GdbUIPlugin.PLUGIN_ID; + + /** image identifier. */ + public static final String IMG_WIZBAN_ADVANCED_TIMEOUT_SETTINGS = PLUGIN_ID + ".imageAdvancedTimeoutSettings"; //$NON-NLS-1$ +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.java new file mode 100644 index 00000000000..1b8f0f53bd2 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2011 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal.ui; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + public static String GdbStatusHandler_Error; + + public static String GdbStatusHandler_Information; + + public static String GdbStatusHandler_Warning; + static { + // initialize resource bundle + NLS.initializeMessages( Messages.class.getName(), Messages.class ); + } + + private Messages() { + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.properties new file mode 100644 index 00000000000..765b50e87aa --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/Messages.properties @@ -0,0 +1,14 @@ +####################################################################################### +# Copyright (c) 2012 Mentor Graphics and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Mentor Graphics - Initial API and implementation +####################################################################################### + +GdbStatusHandler_Error=Error +GdbStatusHandler_Information=Information +GdbStatusHandler_Warning=Warning diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/GdbDebugPreferencePage.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/GdbDebugPreferencePage.java index 7277956d3f1..e6d688d2b56 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/GdbDebugPreferencePage.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/GdbDebugPreferencePage.java @@ -13,25 +13,62 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.preferences; import java.io.File; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.eclipse.cdt.dsf.debug.internal.ui.preferences.IntegerWithBooleanFieldEditor; import org.eclipse.cdt.dsf.debug.internal.ui.preferences.StringWithBooleanFieldEditor; import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; -import org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchUIMessages; +import org.eclipse.cdt.dsf.gdb.internal.ui.IGdbUIConstants; +import org.eclipse.cdt.dsf.gdb.service.command.CustomTimeoutsMap; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.ICellEditorListener; +import org.eclipse.jface.viewers.ICellEditorValidator; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.PlatformUI; @@ -41,6 +78,7 @@ import org.eclipse.ui.PlatformUI; */ @SuppressWarnings("restriction") public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { + /** * A vehicle in order to be able to register a selection listener with * a {@link BooleanFieldEditor}. @@ -58,20 +96,428 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements } } + class AdvancedTimeoutSettingsDialog extends TitleAreaDialog { + + class CommandTimeoutEntry { + + String fCommand; + Integer fTimeout; + + CommandTimeoutEntry( String command, Integer timeout ) { + fCommand = command; + fTimeout = timeout; + } + } + + class CellEditorListener implements ICellEditorListener { + + CellEditor fEditor; + + public CellEditorListener( CellEditor editor ) { + super(); + fEditor = editor; + } + + @Override + public void editorValueChanged( boolean oldValidState, boolean newValidState ) { + if ( newValidState ) { + setErrorMessage( null ); + } + else { + setErrorMessage( fEditor.getErrorMessage() ); + } + updateDialogButtons(); + } + + @Override + public void cancelEditor() { + } + + @Override + public void applyEditorValue() { + validate(); + updateDialogButtons(); + } + }; + + abstract class AbstractEditingSupport extends EditingSupport { + + public AbstractEditingSupport( ColumnViewer viewer ) { + super( viewer ); + } + + @Override + protected void setValue( Object element, Object value ) { + if ( element instanceof CommandTimeoutEntry && value instanceof String ) { + if ( processValue( (CommandTimeoutEntry)element, (String)value ) ) { + fViewer.refresh( element ); + validate(); + updateDialogButtons(); + } + } + } + + @Override + protected Object getValue( Object element ) { + if ( element instanceof CommandTimeoutEntry ) { + return doGetValue( (CommandTimeoutEntry)element ); + } + return null; + } + + @Override + protected CellEditor getCellEditor( Object element ) { + final CellEditor editor = new TextCellEditor( (Composite)getViewer().getControl() ); + editor.setValidator( getValidator() ); + editor.addListener( new CellEditorListener( editor ) ); + return editor; + } + + @Override + protected boolean canEdit( Object element ) { + return ( element instanceof CommandTimeoutEntry ); + } + + abstract boolean processValue( CommandTimeoutEntry entry, String value ); + + abstract Object doGetValue( CommandTimeoutEntry entry ); + + abstract ICellEditorValidator getValidator(); + }; + + private TableViewer fViewer; + private Button fAddButton; + private Button fDeleteButton; + + private List fEntries; + + final private ICellEditorValidator fCommandValidator = new ICellEditorValidator() { + + @Override + public String isValid( Object value ) { + if ( value instanceof String && ((String)value).trim().length() == 0 ) { + return MessagesForPreferences.GdbDebugPreferencePage_Command_field_can_not_be_empty; + } + return null; + } + }; + + final private ICellEditorValidator fTimeoutValidator = new ICellEditorValidator() { + + @Override + public String isValid( Object value ) { + if ( value instanceof String ) { + try { + int intValue = Integer.decode( (String)value ).intValue(); + if ( intValue < 0 ) + return MessagesForPreferences.GdbDebugPreferencePage_Timeout_value_can_not_be_negative; + } + catch( NumberFormatException e ) { + return MessagesForPreferences.GdbDebugPreferencePage_Invalid_timeout_value; + } + } + return null; + } + }; + + AdvancedTimeoutSettingsDialog( Shell parentShell, Set> entries ) { + super( parentShell ); + setShellStyle(getShellStyle() | SWT.RESIZE); + fEntries = new LinkedList(); + for ( Map.Entry entry : entries ) { + fEntries.add( new CommandTimeoutEntry( entry.getKey(), entry.getValue() ) ); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createDialogArea( Composite parent ) { + getShell().setText( MessagesForPreferences.GdbDebugPreferencePage_Advanced_Timeout_Settings ); + setTitle( MessagesForPreferences.GdbDebugPreferencePage_Advanced_timeout_dialog_title ); + setTitleImage( GdbUIPlugin.getImage( IGdbUIConstants.IMG_WIZBAN_ADVANCED_TIMEOUT_SETTINGS ) ); + setMessage( MessagesForPreferences.GdbDebugPreferencePage_Advanced_timeout_dialog_message ); + + Composite control = (Composite)super.createDialogArea( parent ); + Composite comp = new Composite( control, SWT.NONE ); + GridData gd = new GridData( SWT.FILL, SWT.FILL, true, true ); + GridLayout layout = new GridLayout( 2, false ); + layout.marginLeft = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + comp.setLayout( layout ); + comp.setLayoutData( gd ); + + fViewer = new TableViewer( comp, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER ); + final Table table = fViewer.getTable(); + gd = new GridData( SWT.FILL, SWT.FILL, true, true ); + gd.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + table.setLayoutData( gd ); + + ControlDecoration decoration = new ControlDecoration( table, SWT.TOP | SWT.LEFT, control ); + decoration.setImage( + FieldDecorationRegistry.getDefault().getFieldDecoration( + FieldDecorationRegistry.DEC_INFORMATION ).getImage() ); + decoration.setDescriptionText( + MessagesForPreferences.GdbDebugPreferencePage_Advanced_timeout_settings_dialog_tooltip ); + fViewer.addDoubleClickListener( new IDoubleClickListener() { + @Override + public void doubleClick( DoubleClickEvent event ) { + okPressed(); + } + } ); + + fViewer.addSelectionChangedListener( new ISelectionChangedListener() { + + @Override + public void selectionChanged( SelectionChangedEvent event ) { + updateDialogButtons(); + } + } ); + + Composite btnComp = new Composite( comp, SWT.NONE ); + btnComp.setLayout( new GridLayout() ); + btnComp.setLayoutData( new GridData( SWT.RIGHT, SWT.TOP, false, false ) ); + + fAddButton = new Button( btnComp, SWT.PUSH ); + fAddButton.setText( MessagesForPreferences.GdbDebugPreferencePage_Add_button ); + fAddButton.setFont( JFaceResources.getDialogFont() ); + setButtonLayoutData( fAddButton ); + fAddButton.addSelectionListener( new SelectionAdapter() { + + @Override + public void widgetSelected( SelectionEvent e ) { + addNewEntry(); + } + } ); + + fDeleteButton = new Button( btnComp, SWT.PUSH ); + fDeleteButton.setText( MessagesForPreferences.GdbDebugPreferencePage_Delete_button ); + fDeleteButton.setFont( JFaceResources.getDialogFont() ); + setButtonLayoutData( fDeleteButton ); + fDeleteButton.addSelectionListener( new SelectionAdapter() { + + @Override + public void widgetSelected( SelectionEvent e ) { + deleteEntries(); + } + } ); + + table.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) ); + table.setHeaderVisible( true ); + table.setLinesVisible( true ); + + TableViewerColumn commandColumn = new TableViewerColumn( fViewer, SWT.LEFT ); + commandColumn.getColumn().setText( MessagesForPreferences.GdbDebugPreferencePage_Command_column_name ); + commandColumn.setLabelProvider( createCommandLabelProvider() ); + commandColumn.setEditingSupport( createCommandEditingSupport( fViewer ) ); + + TableViewerColumn timeoutColumn = new TableViewerColumn( fViewer, SWT.LEFT ); + timeoutColumn.getColumn().setText( MessagesForPreferences.GdbDebugPreferencePage_Timeout_column_name ); + timeoutColumn.setLabelProvider( createTimeoutLabelProvider() ); + timeoutColumn.setEditingSupport( createTimeoutEditingSupport( fViewer ) ); + + fViewer.setContentProvider( createCustomTimeoutsContentProvider() ); + + table.addControlListener( new ControlAdapter() { + + @Override + public void controlResized( ControlEvent e ) { + Rectangle area = table.getClientArea(); + if ( area.width > 0 ) { + TableColumn[] cols = table.getColumns(); + cols[0].setWidth( area.width * 50 / 100 ); + cols[1].setWidth( area.width * 50 / 100 ); + table.removeControlListener( this ); + } + } + } ); + + fViewer.setInput( fEntries ); + + updateDialogButtons(); + + return control; + } + + void updateDialogButtons() { + if ( fViewer != null && fDeleteButton != null ) { + fDeleteButton.setEnabled( !fViewer.getSelection().isEmpty() ); + } + Button okButton = getButton( IDialogConstants.OK_ID ); + if ( okButton != null ) + okButton.setEnabled( getErrorMessage() == null ); + } + + void addNewEntry() { + CommandTimeoutEntry newEntry = new CommandTimeoutEntry( "", Integer.valueOf( 0 ) ); //$NON-NLS-1$ + fEntries.add( newEntry ); + fViewer.refresh(); + fViewer.setSelection( new StructuredSelection( newEntry ) ); + validateEntry( newEntry ); + updateDialogButtons(); + fViewer.editElement( newEntry, 0 ); + } + + void deleteEntries() { + IStructuredSelection sel = (IStructuredSelection)fViewer.getSelection(); + if ( !sel.isEmpty() ) + fEntries.removeAll( sel.toList() ); + fViewer.refresh(); + validate(); + updateDialogButtons(); + } + + CustomTimeoutsMap getResult() { + CustomTimeoutsMap map = new CustomTimeoutsMap(); + for ( CommandTimeoutEntry entry : fEntries ) { + map.put( entry.fCommand, entry.fTimeout ); + } + return map; + } + + void validate() { + for ( CommandTimeoutEntry entry : fEntries ) { + validateEntry( entry ); + } + } + + void validateEntry( CommandTimeoutEntry entry ) { + String errorMessage = fCommandValidator.isValid( entry.fCommand ); + setErrorMessage( ( errorMessage != null ) ? + errorMessage : fTimeoutValidator.isValid( entry.fTimeout.toString() ) ); + } + + IStructuredContentProvider createCustomTimeoutsContentProvider() { + return new IStructuredContentProvider() { + + @Override + public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) { + } + + @Override + public void dispose() { + } + + @Override + public Object[] getElements( Object inputElement ) { + if ( inputElement instanceof List ) { + @SuppressWarnings( "unchecked" ) + List list = (List)inputElement; + return list.toArray( new Object[list.size()] ); + } + return null; + } + }; + } + + ColumnLabelProvider createCommandLabelProvider() { + return new ColumnLabelProvider() { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object) + */ + @Override + public String getText( Object element ) { + if ( element instanceof CommandTimeoutEntry ) { + return ((CommandTimeoutEntry)element).fCommand; + } + return super.getText( element ); + } + }; + } + + ColumnLabelProvider createTimeoutLabelProvider() { + return new ColumnLabelProvider() { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object) + */ + @Override + public String getText( Object element ) { + if ( element instanceof CommandTimeoutEntry ) { + return ((CommandTimeoutEntry)element).fTimeout.toString(); + } + return super.getText( element ); + } + }; + } + + EditingSupport createCommandEditingSupport( ColumnViewer viewer ) { + return new AbstractEditingSupport( viewer ) { + + @Override + boolean processValue( CommandTimeoutEntry entry, String value ) { + entry.fCommand = value; + return true; + } + + @Override + Object doGetValue( CommandTimeoutEntry entry ) { + return entry.fCommand; + } + + @Override + ICellEditorValidator getValidator() { + return fCommandValidator; + } + }; + } + + EditingSupport createTimeoutEditingSupport( ColumnViewer viewer ) { + return new AbstractEditingSupport( viewer ) { + + @Override + boolean processValue( CommandTimeoutEntry entry, String value ) { + try { + entry.fTimeout = Integer.decode( value ); + return true; + } + catch( NumberFormatException e ) { + // Shouldn't happen, validator takes care of this case. + } + return false; + } + + @Override + Object doGetValue( CommandTimeoutEntry entry ) { + return entry.fTimeout.toString(); + } + + @Override + ICellEditorValidator getValidator() { + return fTimeoutValidator; + } + }; + } + } + + private IntegerWithBooleanFieldEditor fCommandTimeoutField; + private Button fTimeoutAdvancedButton; + + private CustomTimeoutsMap fCustomTimeouts; + public GdbDebugPreferencePage() { super(FLAT); IPreferenceStore store= GdbUIPlugin.getDefault().getPreferenceStore(); setPreferenceStore(store); setDescription(MessagesForPreferences.GdbDebugPreferencePage_description); + fCustomTimeouts = new CustomTimeoutsMap(); } @Override public void init(IWorkbench workbench) { } + @Override + protected void initialize() { + super.initialize(); + initializeCustomTimeouts(); + } + @Override public void createControl(Composite parent) { super.createControl(parent); + updateTimeoutButtons(); PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), GdbUIPlugin.PLUGIN_ID + ".dsfgdb_preference_page"); //$NON-NLS-1$ } @@ -91,44 +537,46 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements final StringFieldEditor stringFieldEditorCommand = new StringFieldEditor( IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_COMMAND, - LaunchUIMessages.getString("GDBDebuggerPage.gdb_debugger"), //$NON-NLS-1$ + "GDB debugger:", //$NON-NLS-1$ group1); stringFieldEditorCommand.fillIntoGrid(group1, 2); addField(stringFieldEditorCommand); Button browsebutton = new Button(group1, SWT.PUSH); - browsebutton.setText(LaunchUIMessages.getString("GDBDebuggerPage.gdb_browse")); //$NON-NLS-1$ + browsebutton.setText("&Browse..."); //$NON-NLS-1$ browsebutton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - handleBrowseButtonSelected(LaunchUIMessages.getString("GDBDebuggerPage.gdb_browse_dlg_title"), //$NON-NLS-1$ + handleBrowseButtonSelected("GDB Debugger", //$NON-NLS-1$ stringFieldEditorCommand); } }); + setButtonLayoutData( browsebutton ); final StringFieldEditor stringFieldEditorGdbInit = new StringFieldEditor( IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_INIT, - LaunchUIMessages.getString("GDBDebuggerPage.gdb_command_file"), //$NON-NLS-1$ + "GDB command file:", //$NON-NLS-1$ group1); stringFieldEditorGdbInit.fillIntoGrid(group1, 2); addField(stringFieldEditorGdbInit); browsebutton = new Button(group1, SWT.PUSH); - browsebutton.setText(LaunchUIMessages.getString("GDBDebuggerPage.gdb_browse")); //$NON-NLS-1$ + browsebutton.setText("&Browse..."); //$NON-NLS-1$ browsebutton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - handleBrowseButtonSelected(LaunchUIMessages.getString("GDBDebuggerPage.gdb_cmdfile_dlg_title"), //$NON-NLS-1$ + handleBrowseButtonSelected("GDB Command File", //$NON-NLS-1$ stringFieldEditorGdbInit); } }); + setButtonLayoutData( browsebutton ); final StringWithBooleanFieldEditor enableStopAtMain = new StringWithBooleanFieldEditor( IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN, IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN_SYMBOL, - LaunchUIMessages.getString("CDebuggerTab.Stop_at_main_on_startup"), //$NON-NLS-1$ + "Stop on startup at:", //$NON-NLS-1$ group1); - enableStopAtMain.fillIntoGrid(group1, 2); + enableStopAtMain.fillIntoGrid(group1, 3); addField(enableStopAtMain); // final StringFieldEditor stopAtMainSymbol = new StringFieldEditor( @@ -145,9 +593,29 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements // } // }); + fCommandTimeoutField = new IntegerWithBooleanFieldEditor( + IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, + IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, + MessagesForPreferences.GdbDebugPreferencePage_Command_timeout, + group1); + fCommandTimeoutField.setValidRange(0, Integer.MAX_VALUE); + fCommandTimeoutField.fillIntoGrid(group1, 2); + addField(fCommandTimeoutField); + + fTimeoutAdvancedButton = new Button(group1, SWT.PUSH); + fTimeoutAdvancedButton.setText(MessagesForPreferences.GdbDebugPreferencePage_Advanced_button); + fTimeoutAdvancedButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + handleAdvancedButtonSelected( + "GDB Debugger"); //$NON-NLS-1$ + } + }); + setButtonLayoutData( fTimeoutAdvancedButton ); + final ListenableBooleanFieldEditor enableNonStop= new ListenableBooleanFieldEditor( IGdbDebugPreferenceConstants.PREF_DEFAULT_NON_STOP, - LaunchUIMessages.getString("GDBDebuggerPage.nonstop_mode"), //$NON-NLS-1$ + "Non-stop mode (Note: Requires non-stop GDB)", //$NON-NLS-1$ SWT.NONE, group1); enableNonStop.fillIntoGrid(group1, 3); addField(enableNonStop); @@ -286,8 +754,56 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements stringFieldEditor.setStringValue(res); } + private void handleAdvancedButtonSelected(String dialogTitle) { + AdvancedTimeoutSettingsDialog dialog = + new AdvancedTimeoutSettingsDialog( getShell(), fCustomTimeouts.entrySet() ); + if ( dialog.open() == Window.OK ) { + fCustomTimeouts = dialog.getResult(); + } + } + @Override protected void adjustGridLayout() { // do nothing } + + @Override + public void propertyChange( PropertyChangeEvent event ) { + if ( event.getSource().equals( fCommandTimeoutField ) && event.getNewValue() instanceof Boolean ) { + fTimeoutAdvancedButton.setEnabled( ((Boolean)event.getNewValue()).booleanValue() ); + } + super.propertyChange( event ); + } + + @Override + protected void performDefaults() { + IPreferenceStore store = getPreferenceStore(); + if ( store != null ) { + String memento = store.getDefaultString( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS ); + fCustomTimeouts.initializeFromMemento( memento ); + } + super.performDefaults(); + updateTimeoutButtons(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.FieldEditorPreferencePage#performOk() + */ + @Override + public boolean performOk() { + getPreferenceStore().setValue( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS, fCustomTimeouts.getMemento() ); + return super.performOk(); + } + + private void updateTimeoutButtons() { + fTimeoutAdvancedButton.setEnabled( fCommandTimeoutField.getBooleanValue() ); + } + + private void initializeCustomTimeouts() { + IPreferenceStore store = getPreferenceStore(); + if ( store != null ) { + String memento = store.getString( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS ); + fCustomTimeouts.initializeFromMemento( memento ); + } + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.java index 43f30999338..752701a87b2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.java @@ -17,6 +17,12 @@ import org.eclipse.osgi.util.NLS; * Preference strings. */ class MessagesForPreferences extends NLS { + public static String GdbDebugPreferencePage_Add_button; + public static String GdbDebugPreferencePage_Advanced_button; + public static String GdbDebugPreferencePage_Advanced_timeout_dialog_message; + public static String GdbDebugPreferencePage_Advanced_timeout_dialog_title; + public static String GdbDebugPreferencePage_Advanced_timeout_settings_dialog_tooltip; + public static String GdbDebugPreferencePage_Advanced_Timeout_Settings; public static String GdbDebugPreferencePage_description; public static String GdbDebugPreferencePage_traces_label; public static String GdbDebugPreferencePage_enableTraces_label; @@ -24,6 +30,9 @@ class MessagesForPreferences extends NLS { public static String GdbDebugPreferencePage_maxGdbTraces_label; public static String GdbDebugPreferencePage_termination_label; public static String GdbDebugPreferencePage_autoTerminateGdb_label; + public static String GdbDebugPreferencePage_Command_column_name; + public static String GdbDebugPreferencePage_Command_field_can_not_be_empty; + public static String GdbDebugPreferencePage_Command_timeout; public static String GdbDebugPreferencePage_hover_label; public static String GdbDebugPreferencePage_useInspectorHover_label; /** @since 2.2 */ @@ -36,6 +45,10 @@ class MessagesForPreferences extends NLS { public static String GdbDebugPreferencePage_initialChildCountLimitForCollections_label; /** @since 2.2 */ public static String GdbDebugPreferencePage_defaults_label; + public static String GdbDebugPreferencePage_Delete_button; + public static String GdbDebugPreferencePage_Invalid_timeout_value; + public static String GdbDebugPreferencePage_Timeout_column_name; + public static String GdbDebugPreferencePage_Timeout_value_can_not_be_negative; static { // initialize resource bundle NLS.initializeMessages(MessagesForPreferences.class.getName(), MessagesForPreferences.class); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.properties index 849a567443a..954149f1345 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/preferences/MessagesForPreferences.properties @@ -10,6 +10,7 @@ # Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121) ############################################################################### +GdbDebugPreferencePage_Add_button=Add GdbDebugPreferencePage_description=General settings for GDB Debugging GdbDebugPreferencePage_traces_label=Traces @@ -17,6 +18,9 @@ GdbDebugPreferencePage_enableTraces_label=Enable GDB traces GdbDebugPreferencePage_maxGdbTraces_label=Limit GDB traces output (number of characters): GdbDebugPreferencePage_termination_label=Termination GdbDebugPreferencePage_autoTerminateGdb_label=Terminate GDB when last process exits +GdbDebugPreferencePage_Command_column_name=GDB/MI Command +GdbDebugPreferencePage_Command_field_can_not_be_empty='Command' field can not be empty +GdbDebugPreferencePage_Command_timeout=Command timeout (ms): GdbDebugPreferencePage_hover_label=Debug Text Hover GdbDebugPreferencePage_useInspectorHover_label=Use enhanced debug hover @@ -27,3 +31,13 @@ GdbDebugPreferencePage_enablePrettyPrinting_label2=(requires python-enabled GDB) GdbDebugPreferencePage_initialChildCountLimitForCollections_label=For collections, initially limit child count to GdbDebugPreferencePage_defaults_label=Debug Configurations Defaults +GdbDebugPreferencePage_Delete_button=Delete +GdbDebugPreferencePage_Invalid_timeout_value=Invalid timeout value +GdbDebugPreferencePage_Timeout_column_name=Timeout(ms) +GdbDebugPreferencePage_Timeout_value_can_not_be_negative=Timeout value can not be negative + +GdbDebugPreferencePage_Advanced_button=&Advanced... +GdbDebugPreferencePage_Advanced_timeout_dialog_message=Specify commands and corresponding timeout values. +GdbDebugPreferencePage_Advanced_timeout_dialog_title=Add/delete/modify custom timeouts for GDB/MI commands +GdbDebugPreferencePage_Advanced_timeout_settings_dialog_tooltip=Specify commands and corresponding timeout values, use zero for "no timeout".\nMI commands must start with hyphen ('-'). For example, '-target-select'.\nThe default value will be used for all commands that are not mentioned here. +GdbDebugPreferencePage_Advanced_Timeout_Settings=Advanced Timeout Settings diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.options b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.options index 28eeb8b6aa9..b9256aedc6e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.options +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.options @@ -1 +1,2 @@ org.eclipse.cdt.dsf.gdb/debug = false +org.eclipse.cdt.dsf.gdb/debug/timeouts = false diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugConstants.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugConstants.java index f50d84f1021..a56582932cf 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugConstants.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugConstants.java @@ -16,7 +16,6 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext; - /** * @noimplement This interface is not intended to be implemented by clients. * @since 4.0 @@ -25,6 +24,12 @@ public interface IGdbDebugConstants { public static final String PREFIX = GdbPlugin.PLUGIN_ID + "."; //$NON-NLS-1$ + /** + * Status code for which a UI handler is registered. + * @since 4.1 + */ + public static final int STATUS_HANDLER_CODE = 20001; + /** * Attribute key to be added to the IProcess associated with an IMIContainerDMContext. * The value should be the groupId as returned by {@link IMIContainerDMContext#getGroupId()} @@ -54,6 +59,5 @@ public interface IGdbDebugConstants { */ public static final String GDB_PROCESS_CREATION_VALUE = PREFIX + "gdbProcess"; //$NON-NLS-1$ - } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugPreferenceConstants.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugPreferenceConstants.java index acc62431fc4..8a77e886b18 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugPreferenceConstants.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGdbDebugPreferenceConstants.java @@ -19,6 +19,11 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; * @since 2.0 */ public interface IGdbDebugPreferenceConstants { + + /** + * Help prefixes. + */ + public static final String PREFIX = GdbPlugin.PLUGIN_ID + "."; //$NON-NLS-1$ /** * Boolean preference whether to enable GDB traces. Default is true. @@ -87,8 +92,27 @@ public interface IGdbDebugPreferenceConstants { public static final String PREF_DEFAULT_NON_STOP = "defaultNonStop"; //$NON-NLS-1$ /** - * Help prefixes. - */ - public static final String PREFIX = GdbPlugin.PLUGIN_ID + "."; //$NON-NLS-1$ + * The value is an boolean specifying whether the timeout is used for GDB commands. + * @since 4.1 + */ + public static final String PREF_COMMAND_TIMEOUT = PREFIX + "commandTimeout"; //$NON-NLS-1$ + + /** + * The value is an integer specifying the timeout value (milliseconds) for GDB commands. + * @since 4.1 + */ + public static final String PREF_COMMAND_TIMEOUT_VALUE = PREFIX + "commandTimeoutValue"; //$NON-NLS-1$ + + /** + * The value is a string specifying the list of GDB/MI commands with custom timeout values. + * @since 4.1 + */ + public static final String PREF_COMMAND_CUSTOM_TIMEOUTS = PREFIX + "commandCustomTimeouts"; //$NON-NLS-1$ + + /** + * Default default value for PREF_COMMAND_TIMEOUT; + * @since 4.1 + */ + public static final int COMMAND_TIMEOUT_VALUE_DEFAULT = 10000; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPreferenceInitializer.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPreferenceInitializer.java index e9403f12ba9..92d0a08d776 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPreferenceInitializer.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPreferenceInitializer.java @@ -38,5 +38,7 @@ public class GdbPreferenceInitializer extends AbstractPreferenceInitializer { node.putBoolean(IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT); node.put(IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT); node.putBoolean(IGdbDebugPreferenceConstants.PREF_DEFAULT_NON_STOP, IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT); + node.putBoolean(IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, false); + node.putInt(IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.java new file mode 100644 index 00000000000..ee19d3c3678 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2011 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + + public static String CustomTimeoutsMap_Error_initializing_custom_timeouts; + + public static String CustomTimeoutsMap_Invalid_custom_timeout_data; + + public static String CustomTimeoutsMap_Invalid_custom_timeout_value; + + public static String GDBControl_Session_is_terminated; + static { + // initialize resource bundle + NLS.initializeMessages( Messages.class.getName(), Messages.class ); + } + + private Messages() { + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.properties new file mode 100644 index 00000000000..9a4e8c3dbbe --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/Messages.properties @@ -0,0 +1,15 @@ +####################################################################################### +# Copyright (c) 2011 Mentor Graphics and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Mentor Graphics - Initial API and implementation +####################################################################################### + +CustomTimeoutsMap_Error_initializing_custom_timeouts=Error initializing custom timeouts +CustomTimeoutsMap_Invalid_custom_timeout_data=Invalid custom timeout data. +CustomTimeoutsMap_Invalid_custom_timeout_value=Invalid custom timeout value for '%s'. +GDBControl_Session_is_terminated=Session is terminated.\nReason: %s diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/CustomTimeoutsMap.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/CustomTimeoutsMap.java new file mode 100644 index 00000000000..503ec1a48c1 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/CustomTimeoutsMap.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2011 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.service.command; + +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.internal.Messages; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Status; + +/** + * @since 4.1 + */ +public class CustomTimeoutsMap extends HashMap { + + public CustomTimeoutsMap() { + super(); + } + + public CustomTimeoutsMap( CustomTimeoutsMap map ) { + super( map ); + } + + private static final long serialVersionUID = -8281280275781904870L; + + public String getMemento() { + StringBuilder sb = new StringBuilder(); + for ( Map.Entry entry : entrySet() ) { + sb.append( entry.getKey() ); + sb.append( ',' ); + sb.append( entry.getValue().intValue() ); + sb.append( ';' ); + } + return sb.toString(); + } + + public void initializeFromMemento( String memento ) { + clear(); + StringTokenizer st = new StringTokenizer( memento, ";" ); //$NON-NLS-1$ + MultiStatus ms = new MultiStatus( GdbPlugin.PLUGIN_ID, 0, Messages.CustomTimeoutsMap_Error_initializing_custom_timeouts, null ); + while( st.hasMoreTokens() ) { + String token = st.nextToken(); + String[] tokenParts = token.split( "," ); //$NON-NLS-1$ + if ( tokenParts.length == 2 && tokenParts[0].length() > 0 && tokenParts[1].length() > 0 ) { + try { + put( tokenParts[0], Integer.valueOf( tokenParts[1] ) ); + } + catch( NumberFormatException e ) { + ms.add( new Status( + IStatus.ERROR, + GdbPlugin.PLUGIN_ID, + String.format( Messages.CustomTimeoutsMap_Invalid_custom_timeout_value, tokenParts[0] ) ) ); + } + } + else { + ms.add( new Status( + IStatus.ERROR, + GdbPlugin.PLUGIN_ID, + Messages.CustomTimeoutsMap_Invalid_custom_timeout_data ) ); + } + } + if ( !ms.isOK() ) { + GdbPlugin.getDefault().getLog().log( ms ); + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java index dd4b956a7b5..dbd6dc9cac3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java @@ -30,6 +30,7 @@ import java.util.Properties; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; @@ -43,10 +44,14 @@ import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.debug.service.command.ICommandToken; +import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.internal.Messages; import org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence; import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses; +import org.eclipse.cdt.dsf.gdb.service.command.GdbCommandTimeoutManager.ICommandTimeoutListener; import org.eclipse.cdt.dsf.mi.service.IMIBackend; import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent; import org.eclipse.cdt.dsf.mi.service.IMIBackend2; @@ -69,8 +74,10 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.IStatusHandler; import org.osgi.framework.BundleContext; /** @@ -82,6 +89,8 @@ import org.osgi.framework.BundleContext; */ public class GDBControl extends AbstractMIControl implements IGDBControl { + private static final int STATUS_CODE_COMMAND_TIMED_OUT = 20100; + /** * Event indicating that the back end process has started. */ @@ -104,6 +113,20 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { } } + private class TimeoutListener implements ICommandTimeoutListener { + + @Override + public void commandTimedOut(final ICommandToken token) { + getExecutor().execute(new DsfRunnable() { + + @Override + public void run() { + GDBControl.this.commandTimedOut(token); + } + }); + } + } + private GDBControlDMContext fControlDmc; private IGDBBackend fMIBackend; @@ -112,6 +135,10 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { private IEventProcessor fCLICommandProcessor; private AbstractCLIProcess fCLIProcess; + private GdbCommandTimeoutManager fCommandTimeoutManager; + + private ICommandTimeoutListener fTimeoutListener = new TimeoutListener(); + /** * GDBControl is only used for GDB earlier that 7.0. Although -list-features * is available in 6.8, it does not report anything we care about, so @@ -120,6 +147,14 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { private final List fFeatures = new ArrayList(); private Sequence fInitializationSequence; + + /** + * Indicator to distinguish whether this service is initialized. + * fInitializationSequence can not be used for this + * purpose because there is a period of time when the service is already + * initializing but the initialization sequence has not created yet. + */ + private boolean fInitialized = false; private boolean fTerminated; @@ -308,6 +343,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { @Override protected void handleCompleted() { fInitializationSequence = null; + fInitialized = true; if (!isCanceled()) { // Only set the status if the user has not cancelled the operation already. rm.setStatus(getStatus()); @@ -440,6 +476,33 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { } } + /** + * @since 4.1 + */ + protected class CommandTimeoutStep extends InitializationShutdownStep { + CommandTimeoutStep( Direction direction ) { + super( direction ); + } + + @Override + public void initialize( final RequestMonitor requestMonitor ) { + fCommandTimeoutManager = createCommandTimeoutManager( GDBControl.this ); + if (fCommandTimeoutManager != null) { + fCommandTimeoutManager.addCommandTimeoutListener(fTimeoutListener); + } + requestMonitor.done(); + } + + @Override + protected void shutdown( RequestMonitor requestMonitor ) { + if ( fCommandTimeoutManager != null ) { + fCommandTimeoutManager.removeCommandTimeoutListener(fTimeoutListener); + fCommandTimeoutManager.dispose(); + } + requestMonitor.done(); + } + } + protected class RegisterStep extends InitializationShutdownStep { RegisterStep(Direction direction) { super(direction); } @Override @@ -493,6 +556,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { final Sequence.Step[] initializeSteps = new Sequence.Step[] { new CommandMonitoringStep(InitializationShutdownStep.Direction.INITIALIZING), new CommandProcessorsStep(InitializationShutdownStep.Direction.INITIALIZING), + new CommandTimeoutStep(InitializationShutdownStep.Direction.INITIALIZING), new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING), }; @@ -507,6 +571,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { protected Sequence getShutdownSequence(RequestMonitor requestMonitor) { final Sequence.Step[] shutdownSteps = new Sequence.Step[] { new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN), + new CommandTimeoutStep(InitializationShutdownStep.Direction.SHUTTING_DOWN), new CommandProcessorsStep(InitializationShutdownStep.Direction.SHUTTING_DOWN), new CommandMonitoringStep(InitializationShutdownStep.Direction.SHUTTING_DOWN), }; @@ -536,4 +601,63 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { fFeatures.clear(); fFeatures.addAll(features); } + + /** + * @since 4.1 + */ + protected GdbCommandTimeoutManager createCommandTimeoutManager(ICommandControl commandControl) { + GdbCommandTimeoutManager manager = new GdbCommandTimeoutManager(commandControl); + manager.initialize(); + return manager; + } + + /** + * @since 4.1 + */ + @ConfinedToDsfExecutor("this.getExecutor()") + protected void commandTimedOut(ICommandToken token) { + String commandText = token.getCommand().toString(); + if (commandText.endsWith("\n")) //$NON-NLS-1$ + commandText = commandText.substring(0, commandText.length() - 1); + final String errorMessage = String.format("Command '%s' is timed out", commandText); //$NON-NLS-1$ + commandFailed(token, STATUS_CODE_COMMAND_TIMED_OUT, errorMessage); + + // If the timeout occurs while the launch sequence is running + // the error will be reported by the launcher's error reporting mechanism. + // We need to show the error message only when the session is initialized. + if (isInitialized()) { + // The session is terminated if a command is timed out. + terminate(new RequestMonitor(getExecutor(), null) { + + @Override + protected void handleErrorOrWarning() { + GdbPlugin.getDefault().getLog().log(getStatus()); + super.handleErrorOrWarning(); + }; + } ); + + IStatus status = new Status( + IStatus.ERROR, + GdbPlugin.PLUGIN_ID, + IGdbDebugConstants.STATUS_HANDLER_CODE, + String.format( Messages.GDBControl_Session_is_terminated, errorMessage ), + null); + IStatusHandler statusHandler = DebugPlugin.getDefault().getStatusHandler(status); + if (statusHandler != null) { + try { + statusHandler.handleStatus(status, null); + } + catch(CoreException e) { + GdbPlugin.getDefault().getLog().log(e.getStatus()); + } + } + } + } + + /** + * @since 4.1 + */ + protected boolean isInitialized() { + return fInitialized; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java index 3a780424602..55f4aa15860 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java @@ -147,6 +147,7 @@ public class GDBControl_7_0 extends GDBControl { final Sequence.Step[] initializeSteps = new Sequence.Step[] { new GDBControl.CommandMonitoringStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING), new GDBControl.CommandProcessorsStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING), + new CommandTimeoutStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING), new ListFeaturesStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING), new GDBControl.RegisterStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING), }; @@ -161,6 +162,7 @@ public class GDBControl_7_0 extends GDBControl { final Sequence.Step[] shutdownSteps = new Sequence.Step[] { new GDBControl.RegisterStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN), new ListFeaturesStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN), + new CommandTimeoutStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN), new GDBControl.CommandProcessorsStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN), new GDBControl.CommandMonitoringStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN), }; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GdbCommandTimeoutManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GdbCommandTimeoutManager.java new file mode 100644 index 00000000000..133865c1a95 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GdbCommandTimeoutManager.java @@ -0,0 +1,443 @@ +/******************************************************************************* + * Copyright (c) 2011 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.service.command; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import org.eclipse.cdt.dsf.debug.service.command.ICommand; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; +import org.eclipse.cdt.dsf.debug.service.command.ICommandListener; +import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; +import org.eclipse.cdt.dsf.debug.service.command.ICommandToken; +import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl; +import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; +import org.eclipse.core.runtime.preferences.InstanceScope; + +/** + * The command timeout manager registers itself as a command listener and monitors + * the command execution time. The goal of this implementation is to gracefully + * handle disruptions in the communication between Eclipse and GDB. + * + * The algorithm used by this class is based on the assumption that the command + * execution in GDB is sequential even though DSF can send up to 3 commands at + * a time to GDB (see {@link AbstractMIControl}). + * + * @since 4.1 + */ +public class GdbCommandTimeoutManager implements ICommandListener, IPreferenceChangeListener { + + public interface ICommandTimeoutListener { + + void commandTimedOut( ICommandToken token ); + } + + public final static boolean DEBUG = "true".equals( Platform.getDebugOption( "org.eclipse.cdt.dsf.gdb/debug/timeouts" ) ); //$NON-NLS-1$//$NON-NLS-2$ + + private class QueueEntry { + private long fTimestamp; + private ICommandToken fCommandToken; + + private QueueEntry( long timestamp, ICommandToken commandToken ) { + super(); + fTimestamp = timestamp; + fCommandToken = commandToken; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals( Object obj ) { + if ( obj instanceof QueueEntry ) { + return fCommandToken.equals( ((QueueEntry)obj).fCommandToken ); + } + return false; + } + } + + private enum TimerThreadState { + INITIALIZING, + RUNNING, + HALTED, + SHUTDOWN + } + + private class TimerThread extends Thread { + + private BlockingQueue fQueue; + private int fWaitTimeout = IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT; + private TimerThreadState fState = TimerThreadState.INITIALIZING; + + TimerThread( BlockingQueue queue, int timeout ) { + super(); + setName( "GDB Command Timer Thread" ); //$NON-NLS-1$ + fQueue = queue; + setWaitTimout( timeout ); + } + + /* (non-Javadoc) + * @see java.lang.Thread#run() + */ + @Override + public void run() { + setTimerThreadState( ( getWaitTimeout() > 0 ) ? + TimerThreadState.RUNNING : TimerThreadState.HALTED ); + doRun(); + } + + private void doRun() { + while ( getTimerThreadState() != TimerThreadState.SHUTDOWN ) { + if ( getTimerThreadState() == TimerThreadState.HALTED ) { + halted(); + } + else { + running(); + } + } + } + + private void halted() { + fQueue.clear(); + try { + synchronized( TimerThread.this ) { + wait(); + } + } + catch( InterruptedException e ) { + } + } + + private void running() { + try { + while( getTimerThreadState() == TimerThreadState.RUNNING ) { + // Use the minimum of all timeout values > 0 as the wait timeout. + long timeout = getWaitTimeout(); + QueueEntry entry = fQueue.peek(); + if ( entry != null ) { + // Calculate the time elapsed since the execution of this command started + // and compare it with the command's timeout value. + // If the elapsed time is greater or equal than the timeout value the command + // is marked as timed out. Otherwise, schedule the next check when the timeout + // expires. + long commandTimeout = getTimeoutForCommand( entry.fCommandToken.getCommand() ); + + if ( DEBUG ) { + String commandText = entry.fCommandToken.getCommand().toString(); + if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$ + commandText = commandText.substring( 0, commandText.length() - 1 ); + printDebugMessage( String.format( "Processing command '%s', command timeout is %d", //$NON-NLS-1$ + commandText, Long.valueOf( commandTimeout ) ) ); + } + + long currentTime = System.currentTimeMillis(); + long elapsedTime = currentTime - entry.fTimestamp; + if ( commandTimeout <= elapsedTime ) { + processTimedOutCommand( entry.fCommandToken ); + fQueue.remove( entry ); + // Reset the timestamp of the next command in the queue because + // regardless how long the command has been in the queue GDB will + // start executing it only when the execution of the previous command + // is completed. + QueueEntry nextEntry = fQueue.peek(); + if ( nextEntry != null ) { + setTimeStamp( currentTime, nextEntry ); + } + } + else { + // Adjust the wait timeout because the time remaining for + // the current command to expire may be less than the current wait timeout. + timeout = Math.min( timeout, commandTimeout - elapsedTime ); + + if ( DEBUG ) { + String commandText = entry.fCommandToken.getCommand().toString(); + if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$ + commandText = commandText.substring( 0, commandText.length() - 1 ); + printDebugMessage( String.format( "Setting timeout %d for command '%s'", Long.valueOf( timeout ), commandText ) ); //$NON-NLS-1$ + } + } + } + synchronized( TimerThread.this ) { + wait( timeout ); + } + } + } + catch( InterruptedException e ) { + } + } + + private void shutdown() { + setTimerThreadState( TimerThreadState.SHUTDOWN ); + } + + private synchronized void setWaitTimout( int waitTimeout ) { + fWaitTimeout = waitTimeout; + if ( DEBUG ) + printDebugMessage( String.format( "Wait timeout is set to %d", Integer.valueOf( fWaitTimeout ) ) ); //$NON-NLS-1$ + } + + private synchronized int getWaitTimeout() { + return fWaitTimeout; + } + + private synchronized void setTimerThreadState( TimerThreadState state ) { + fState = state; + interrupt(); + } + + private synchronized TimerThreadState getTimerThreadState() { + return fState; + } + } + + private static final String TIMEOUT_TRACE_IDENTIFIER = "[TMO]"; //$NON-NLS-1$ + + private ICommandControl fCommandControl; + private boolean fTimeoutEnabled = false; + private int fTimeout = 0; + private TimerThread fTimerThread; + private BlockingQueue fCommandQueue = new LinkedBlockingQueue(); + private CustomTimeoutsMap fCustomTimeouts = new CustomTimeoutsMap(); + + private ListenerList fListeners; + + public GdbCommandTimeoutManager( ICommandControl commandControl ) { + fCommandControl = commandControl; + fListeners = new ListenerList(); + } + + public void initialize() { + IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ); + + fTimeoutEnabled = Platform.getPreferencesService().getBoolean( + GdbPlugin.PLUGIN_ID, + IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, + false, + null ); + + fTimeout = Platform.getPreferencesService().getInt( + GdbPlugin.PLUGIN_ID, + IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, + IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT, + null ); + + fCustomTimeouts.initializeFromMemento( Platform.getPreferencesService().getString( + GdbPlugin.PLUGIN_ID, + IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS, + "", //$NON-NLS-1$ + null ) ); + + node.addPreferenceChangeListener( this ); + + fCommandControl.addCommandListener( this ); + + fTimerThread = new TimerThread( fCommandQueue, calculateWaitTimeout() ); + fTimerThread.start(); + } + + public void dispose() { + fTimerThread.shutdown(); + fListeners.clear(); + InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ).removePreferenceChangeListener( this ); + fCommandControl.removeCommandListener( this ); + fCommandQueue.clear(); + fCustomTimeouts.clear(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandQueued(org.eclipse.cdt.dsf.debug.service.command.ICommandToken) + */ + @Override + public void commandQueued( ICommandToken token ) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandSent(org.eclipse.cdt.dsf.debug.service.command.ICommandToken) + */ + @Override + public void commandSent( ICommandToken token ) { + if ( !isTimeoutEnabled() ) + return; + int commandTimeout = getTimeoutForCommand( token.getCommand() ); + if ( DEBUG ) { + String commandText = token.getCommand().toString(); + if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$ + commandText = commandText.substring( 0, commandText.length() - 1 ); + printDebugMessage( String.format( "Command '%s' sent, timeout = %d", commandText, Integer.valueOf( commandTimeout ) ) ); //$NON-NLS-1$ + } + if ( commandTimeout == 0 ) + // Skip commands with no timeout + return; + try { + fCommandQueue.put( new QueueEntry( System.currentTimeMillis(), token ) ); + } + catch( InterruptedException e ) { + // ignore + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandRemoved(org.eclipse.cdt.dsf.debug.service.command.ICommandToken) + */ + @Override + public void commandRemoved( ICommandToken token ) { + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandDone(org.eclipse.cdt.dsf.debug.service.command.ICommandToken, org.eclipse.cdt.dsf.debug.service.command.ICommandResult) + */ + @Override + public void commandDone( ICommandToken token, ICommandResult result ) { + if ( !isTimeoutEnabled() ) + return; + fCommandQueue.remove( new QueueEntry( 0, token ) ); + if ( DEBUG ) { + String commandText = token.getCommand().toString(); + if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$ + commandText = commandText.substring( 0, commandText.length() - 1 ); + printDebugMessage( String.format( "Command '%s' is done", commandText ) ); //$NON-NLS-1$ + } + // Reset the timestamp of the next command in the queue because + // regardless how long it has been in the queue GDB will start + // executing it only when the execution of the previous command + // is completed. + QueueEntry nextEntry = fCommandQueue.peek(); + if ( nextEntry != null ) { + setTimeStamp( System.currentTimeMillis(), nextEntry ); + } + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent) + */ + @Override + public void preferenceChange( PreferenceChangeEvent event ) { + String property = event.getKey(); + if ( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT.equals( property ) ) { + // The new value is null when the timeout support is disabled. + if ( event.getNewValue() == null || !event.getNewValue().equals( event.getOldValue() ) ) { + fTimeoutEnabled = ( event.getNewValue() != null ) ? + Boolean.parseBoolean( event.getNewValue().toString() ) : Boolean.FALSE; + updateWaitTimeout(); + fTimerThread.setTimerThreadState( ( fTimerThread.getWaitTimeout() > 0 ) ? + TimerThreadState.RUNNING : TimerThreadState.HALTED ); + } + } + else if ( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE.equals( property ) ) { + if ( event.getNewValue() == null || !event.getNewValue().equals( event.getOldValue() ) ) { + try { + fTimeout = ( event.getNewValue() != null ) ? + Integer.parseInt( event.getNewValue().toString() ) : + IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT; + updateWaitTimeout(); + fTimerThread.setTimerThreadState( ( fTimerThread.getWaitTimeout() > 0 ) ? + TimerThreadState.RUNNING : TimerThreadState.HALTED ); + } + catch( NumberFormatException e ) { + GdbPlugin.getDefault().getLog().log( new Status( IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invlaid timeout value" ) ); //$NON-NLS-1$ + } + } + } + else if ( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS.equals( property ) ) { + if ( event.getNewValue() instanceof String ) { + fCustomTimeouts.initializeFromMemento( (String)event.getNewValue() ); + } + else if ( event.getNewValue() == null ) { + fCustomTimeouts.clear(); + } + updateWaitTimeout(); + fTimerThread.setTimerThreadState( ( fTimerThread.getWaitTimeout() > 0 ) ? + TimerThreadState.RUNNING : TimerThreadState.HALTED ); + } + } + + protected int getTimeoutForCommand( ICommand command ) { + if ( !(command instanceof MICommand) ) + return 0; + @SuppressWarnings( "unchecked" ) + Integer timeout = fCustomTimeouts.get( ((MICommand)command).getOperation() ); + return ( timeout != null ) ? timeout.intValue() : fTimeout; + } + + protected void processTimedOutCommand( ICommandToken token ) { + if ( DEBUG ) { + String commandText = token.getCommand().toString(); + if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$ + commandText = commandText.substring( 0, commandText.length() - 1 ); + printDebugMessage( String.format( "Command '%s' is timed out", commandText ) ); //$NON-NLS-1$ + } + for ( Object l : fListeners.getListeners() ) { + ((ICommandTimeoutListener)l).commandTimedOut( token ); + } + } + + public void addCommandTimeoutListener( ICommandTimeoutListener listener ) { + fListeners.add( listener ); + } + + public void removeCommandTimeoutListener( ICommandTimeoutListener listener ) { + fListeners.remove( listener ); + } + + private void updateWaitTimeout() { + fTimerThread.setWaitTimout( calculateWaitTimeout() ); + } + + private boolean isTimeoutEnabled() { + return fTimeoutEnabled; + } + + private void printDebugMessage( String message ) { + System.out.println( String.format( "%s %s %s", GdbPlugin.getDebugTime(), TIMEOUT_TRACE_IDENTIFIER, message ) ); //$NON-NLS-1$ + } + + private int calculateWaitTimeout() { + int waitTimeout = 0; + if ( isTimeoutEnabled() ) { + waitTimeout = fTimeout; + int minCustomTimeout = Integer.MAX_VALUE; + for ( Integer t : fCustomTimeouts.values() ) { + if ( t.intValue() > 0 ) { + minCustomTimeout = Math.min( minCustomTimeout, t.intValue() ); + } + } + if ( minCustomTimeout > 0 ) { + waitTimeout = ( waitTimeout == 0 ) ? + minCustomTimeout : Math.min( waitTimeout, minCustomTimeout ); + } + } + return waitTimeout; + } + + private void setTimeStamp( long currentTime, QueueEntry nextEntry ) { + if ( nextEntry != null ) { + nextEntry.fTimestamp = currentTime; + + if ( DEBUG ) { + String commandText = nextEntry.fCommandToken.getCommand().toString(); + if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$ + commandText = commandText.substring( 0, commandText.length() - 1 ); + printDebugMessage( String.format( "Setting the timestamp for command '%s' to %d", commandText, Long.valueOf( currentTime ) ) ); //$NON-NLS-1$ + } + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java index eb2e702a877..6277fbb97ad 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java @@ -29,6 +29,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.datamodel.DMContexts; @@ -874,6 +875,7 @@ public abstract class AbstractMIControl extends AbstractDsfService } void processMIOutput(String line) { + MIParser.RecordType recordType = fMiParser.getRecordType(line); if (recordType == MIParser.RecordType.ResultRecord) { @@ -885,6 +887,7 @@ public abstract class AbstractMIControl extends AbstractDsfService * some form of asynchronous notification. Or perhaps general IO. */ int id = rr.getToken(); + final CommandHandle commandHandle = fRxCommands.remove(id); if (commandHandle != null) { @@ -1098,4 +1101,46 @@ public abstract class AbstractMIControl extends AbstractDsfService fCurrentStackLevel = -1; } + /** + * @since 4.1 + */ + @ConfinedToDsfExecutor("this.getExecutor()") + protected void commandFailed(ICommandToken token, int statusCode, String errorMessage) { + if ( !(token instanceof CommandHandle && token.getCommand() instanceof MICommand) ) + return; + final CommandHandle commandHandle = (CommandHandle)token; + Integer tokenId = commandHandle.getTokenId(); + + // If the timeout value is too small a command can be timed out but still processed by RxThread. + // To avoid processing it twice we need to remove it from the command list. + CommandHandle h = fRxCommands.remove(tokenId); + if (h == null) + // Command has already been processed by RxThread. + return; + + MIConst value = new MIConst(); + value.setCString(errorMessage); + MIResult result = new MIResult(); + result.setVariable("msg"); //$NON-NLS-1$ + result.setMIValue(value); + MIResultRecord resultRecord = new MIResultRecord(); + resultRecord.setToken(tokenId.intValue()); + resultRecord.setResultClass(MIResultRecord.ERROR); + resultRecord.setMIResults(new MIResult[] { result }); + MIOutput miOutput = new MIOutput(resultRecord, new MIOOBRecord[0]); + + final MIInfo info = commandHandle.getCommand().getResult(miOutput); + DataRequestMonitor rm = commandHandle.getRequestMonitor(); + + if ( rm != null ) { + rm.setData(info); + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, statusCode, errorMessage, null)); + rm.done(); + + /* + * Now tell the generic listeners about it. + */ + processCommandDone(commandHandle, info); + } + } } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java index 797e4882983..7d20fe9db2c 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/BaseTestCase.java @@ -91,6 +91,10 @@ public class BaseTestCase { launchAttributes.put(key, value); } + public static void removeLaunchAttribute(String key) { + launchAttributes.remove(key); + } + public static void setGlobalLaunchAttribute(String key, Object value) { globalLaunchAttributes.put(key, value); } @@ -206,7 +210,8 @@ public class BaseTestCase { .equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE); // First check if we should launch gdbserver in the case of a remote session - launchGdbServer(); + if (reallyLaunchGDBServer()) + launchGdbServer(); ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager(); ILaunchConfigurationType lcType = launchMgr.getLaunchConfigurationType("org.eclipse.cdt.tests.dsf.gdb.TestLaunch"); @@ -332,4 +337,14 @@ public class BaseTestCase { BaseTestCase.setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME, "gdb." + version + (isWindows ? ".exe" : "")); BaseTestCase.setLaunchAttribute(ATTR_DEBUG_SERVER_NAME, "gdbserver." + version + (isWindows ? ".exe" : "")); } + + /** + * In some tests we need to start a gdbserver session without starting gdbserver. + * This method allows super classes of this class control the launch of gdbserver. + * + * @return whether gdbserver should be started + */ + protected boolean reallyLaunchGDBServer() { + return true; + } } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/AllTests.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/AllTests.java index 6f0319c88cf..5b00c8877b2 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/AllTests.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/AllTests.java @@ -38,6 +38,7 @@ import org.junit.runners.Suite; LaunchConfigurationAndRestartTest.class, OperationsWhileTargetIsRunningTest.class, PostMortemCoreTest.class, + CommandTimeoutTest.class, Suite_Sessionless_Tests.class, /* Add your suite class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/CommandTimeoutTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/CommandTimeoutTest.java new file mode 100644 index 00000000000..065d6924c15 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/CommandTimeoutTest.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests; + +import junit.framework.Assert; + +import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.debug.core.DebugException; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest extends BaseTestCase { + + private static boolean fgTimeoutEnabled = false; + private static int fgTimeout = IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT; + + @BeforeClass + public static void beforeClassMethod() { + // Save the original values of the timeout-related preferences + fgTimeoutEnabled = Platform.getPreferencesService().getBoolean( + GdbPlugin.PLUGIN_ID, + IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, + false, + null ); + fgTimeout = Platform.getPreferencesService().getInt( + GdbPlugin.PLUGIN_ID, + IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, + IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT, + null ); + } + + @Before + @Override + public void baseBeforeMethod() throws Exception { + } + + @After + @Override + public void baseAfterMethod() throws Exception { + // Restore the timeout preferences + IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ); + node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, fgTimeoutEnabled ); + node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, fgTimeout ); + } + + @Override + protected boolean reallyLaunchGDBServer() { + return false; + } + + /** + * Enables the timeout support and sets the timeout value to minimal - 1. + * Launch is expected to timeout on the first gdb command. + */ + @Test + public void firstCommandTimedOut() { + IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ); + node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true ); + node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 1 ); + + try { + performLaunchAndTerminate(); + Assert.fail( "Launch is expected to fail" ); + } + catch( Exception e ) { + processException( e ); + } + } + + /** + * Tries to connect to gdbserver without starting it. + * Launch is expected to timeout on "target-remote" command. + */ + @Test + public void remoteConnectionTimedOut() { + if ( !isRemoteSession() ) + return; + + IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ); + node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true ); + node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 1000 ); + + try { + performLaunchAndTerminate(); + Assert.fail( "Launch is expected to fail" ); + } + catch( Exception e ) { + processException( e ); + } + } + + private void performLaunchAndTerminate() throws Exception { + super.baseBeforeMethod(); + super.baseAfterMethod(); + } + + /** + * Checks whether the given exception is an instance of {@link CoreException} + * with the status code 20100 which indicates that a gdb command has been timed out. + */ + private void processException( Exception e ) { + if ( e instanceof DebugException ) { + Throwable t = getExceptionCause( e ); + Assert.assertTrue( + "Unexpected exception", + t instanceof CoreException && ((CoreException)t).getStatus().getCode() == 20100 ); + } + else { + Assert.fail( "Unexpected exception type" ); + } + } + + private Throwable getExceptionCause(Throwable e) { + Throwable current = e; + while ( current instanceof CoreException ) { + Throwable t = ((CoreException)current).getCause(); + if ( t == null ) + break; + current = t; + } + return current; + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/CommandTimeoutTest_6_6.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/CommandTimeoutTest_6_6.java new file mode 100644 index 00000000000..2f087862af3 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/CommandTimeoutTest_6_6.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_6_6; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_6_6 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_6_6() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_6_6); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_6_6.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_6_6.java index 987092d6b6b..f83b1204c91 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_6_6.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_6_6.java @@ -38,7 +38,8 @@ import org.junit.runners.Suite; LaunchConfigurationAndRestartTest_6_6.class, OperationsWhileTargetIsRunningTest_6_6.class, PostMortemCoreTest_6_6.class, - Suite_Sessionless_Tests.class + Suite_Sessionless_Tests.class, + CommandTimeoutTest_6_6.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_Remote_6_6.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_Remote_6_6.java index 19d259a4ff0..648d1c45677 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_Remote_6_6.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_6/Suite_Remote_6_6.java @@ -37,7 +37,8 @@ import org.junit.runners.Suite; MIDisassemblyTest_6_6.class, GDBProcessesTest_6_6.class, OperationsWhileTargetIsRunningTest_6_6.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_6_6.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/CommandTimeoutTest_6_7.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/CommandTimeoutTest_6_7.java new file mode 100644 index 00000000000..1ab85b63073 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/CommandTimeoutTest_6_7.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_6_7; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_6_7 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_6_7() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_6_7); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_6_7.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_6_7.java index 3a58408147a..5b3bde605a5 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_6_7.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_6_7.java @@ -38,7 +38,8 @@ import org.junit.runners.Suite; LaunchConfigurationAndRestartTest_6_7.class, OperationsWhileTargetIsRunningTest_6_7.class, PostMortemCoreTest_6_7.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_6_7.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_Remote_6_7.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_Remote_6_7.java index 504ca779574..9e5a278a1fe 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_Remote_6_7.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_7/Suite_Remote_6_7.java @@ -37,7 +37,8 @@ import org.junit.runners.Suite; MIDisassemblyTest_6_7.class, GDBProcessesTest_6_7.class, OperationsWhileTargetIsRunningTest_6_7.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_6_7.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/CommandTimeoutTest_6_8.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/CommandTimeoutTest_6_8.java new file mode 100644 index 00000000000..f8e57790df0 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/CommandTimeoutTest_6_8.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_6_8; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_6_8 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_6_8() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_6_8); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_6_8.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_6_8.java index 6b2b75c984a..61f22592880 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_6_8.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_6_8.java @@ -38,7 +38,8 @@ import org.junit.runners.Suite; LaunchConfigurationAndRestartTest_6_8.class, OperationsWhileTargetIsRunningTest_6_8.class, PostMortemCoreTest_6_8.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_6_8.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_Remote_6_8.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_Remote_6_8.java index 286ad3e06dc..b059d858228 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_Remote_6_8.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_6_8/Suite_Remote_6_8.java @@ -37,7 +37,8 @@ import org.junit.runners.Suite; MIDisassemblyTest_6_8.class, GDBProcessesTest_6_8.class, OperationsWhileTargetIsRunningTest_6_8.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_6_8.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/CommandTimeoutTest_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/CommandTimeoutTest_7_0.java new file mode 100644 index 00000000000..eb8c7759e0a --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/CommandTimeoutTest_7_0.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_0; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_7_0 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_7_0() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_0); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java index 176b45b84f4..68d0e6843f1 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_7_0.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_0.class, OperationsWhileTargetIsRunningNonStopTest_7_0.class, PostMortemCoreTest_7_0.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_0.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java index 3869ccee90d..d267a011a74 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_0/Suite_Remote_7_0.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; GDBProcessesTest_7_0.class, OperationsWhileTargetIsRunningTest_7_0.class, OperationsWhileTargetIsRunningNonStopTest_7_0.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_0.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/CommandTimeoutTest_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/CommandTimeoutTest_7_1.java new file mode 100644 index 00000000000..b3de8a12d57 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/CommandTimeoutTest_7_1.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_1; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_7_1 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_7_1() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_1); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java index c8717d34335..75b9b161c61 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_7_1.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_1.class, OperationsWhileTargetIsRunningNonStopTest_7_1.class, PostMortemCoreTest_7_1.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_1.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java index ac73aa23356..980446d4e95 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_1/Suite_Remote_7_1.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; GDBProcessesTest_7_1.class, OperationsWhileTargetIsRunningTest_7_1.class, OperationsWhileTargetIsRunningNonStopTest_7_1.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_1.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/CommandTimeoutTest_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/CommandTimeoutTest_7_2.java new file mode 100644 index 00000000000..6a88bcc8eea --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/CommandTimeoutTest_7_2.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_2; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_7_2 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_7_2() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_2); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java index 45deeaa2853..800fe29a252 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_7_2.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_2.class, OperationsWhileTargetIsRunningNonStopTest_7_2.class, PostMortemCoreTest_7_2.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_2.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java index 48269bfc10b..32f2a1e7b89 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_2/Suite_Remote_7_2.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; GDBProcessesTest_7_2.class, OperationsWhileTargetIsRunningTest_7_2.class, OperationsWhileTargetIsRunningNonStopTest_7_2.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_2.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/CommandTimeoutTest_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/CommandTimeoutTest_7_3.java new file mode 100644 index 00000000000..624916380dc --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/CommandTimeoutTest_7_3.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_3; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_7_3 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_7_3() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_3); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java index 66843ec2753..65e39402046 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_7_3.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_3.class, OperationsWhileTargetIsRunningNonStopTest_7_3.class, PostMortemCoreTest_7_3.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_3.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java index 5baac54dcf3..63e9e39e29a 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_3/Suite_Remote_7_3.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; GDBProcessesTest_7_3.class, OperationsWhileTargetIsRunningTest_7_3.class, OperationsWhileTargetIsRunningNonStopTest_7_3.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_3.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/CommandTimeoutTest_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/CommandTimeoutTest_7_4.java new file mode 100644 index 00000000000..3974aa66159 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/CommandTimeoutTest_7_4.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_4; + +import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner; +import org.eclipse.cdt.tests.dsf.gdb.tests.CommandTimeoutTest; +import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +@RunWith(BackgroundRunner.class) +public class CommandTimeoutTest_7_4 extends CommandTimeoutTest { + @BeforeClass + public static void beforeClassMethod_7_4() { + setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_4); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java index 7f84cf16bb1..d2c7ea43ec1 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_7_4.java @@ -40,7 +40,8 @@ import org.junit.runners.Suite; OperationsWhileTargetIsRunningTest_7_4.class, OperationsWhileTargetIsRunningNonStopTest_7_4.class, PostMortemCoreTest_7_4.class, - Suite_Sessionless_Tests.class + CommandTimeoutTest_7_4.class, + Suite_Sessionless_Tests.class, /* Add your test class here */ }) diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java index ce61ef09780..f76a836d040 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_4/Suite_Remote_7_4.java @@ -40,6 +40,7 @@ import org.junit.runners.Suite; GDBProcessesTest_7_4.class, OperationsWhileTargetIsRunningTest_7_4.class, OperationsWhileTargetIsRunningNonStopTest_7_4.class, + CommandTimeoutTest_7_4.class, Suite_Sessionless_Tests.class /* Add your test class here */ }) From 0e6e83e1cbbf8ea77962bfd0803500a978933b93 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 17 Apr 2012 15:48:54 -0400 Subject: [PATCH 03/13] Bug 330974: Clean up non-stop runControl services. Change-Id: I6e1eff14072080ba2689b1af12ec4a1f45877241 --- .../dsf/gdb/service/GDBRunControl_7_0_NS.java | 146 +++++++++--------- .../dsf/gdb/service/GDBRunControl_7_2_NS.java | 8 +- 2 files changed, 74 insertions(+), 80 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java index 490f50e54e6..60eb549a3e8 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java @@ -449,9 +449,9 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo return (threadState == null) ? false : !fTerminated && threadState.fSuspended; } - // Container case. The container is considered suspended as long + // Process case. The process is considered suspended as long // as one of its thread is suspended - if (context instanceof IContainerDMContext) { + if (context instanceof IMIContainerDMContext) { boolean hasThread = false; for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) { if (DMContexts.isAncestorOf(threadContext, context)) { @@ -471,39 +471,34 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo @Override public void canSuspend(IExecutionDMContext context, DataRequestMonitor rm) { if (fRunControlOperationsEnabled == false) { - rm.setData(false); - rm.done(); + rm.done(false); return; } + rm.done(doCanSuspend(context)); + } + + private boolean doCanSuspend(IExecutionDMContext context) { // Thread case if (context instanceof IMIExecutionDMContext) { - rm.setData(doCanSuspend(context)); - rm.done(); - return; + MIThreadRunState threadState = fThreadRunStates.get(context); + return (threadState == null) ? false : !fTerminated && !threadState.fSuspended; } - // Container case - if (context instanceof IContainerDMContext) { - boolean canSuspend = false; + // Process case + if (context instanceof IMIContainerDMContext) { for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) { if (DMContexts.isAncestorOf(threadContext, context)) { - canSuspend |= doCanSuspend(threadContext); + if (doCanSuspend(threadContext)) { + return true; + } } } - rm.setData(canSuspend); - rm.done(); - return; + return false; } // Default case - rm.setData(false); - rm.done(); - } - - private boolean doCanSuspend(IExecutionDMContext context) { - MIThreadRunState threadState = fThreadRunStates.get(context); - return (threadState == null) ? false : !fTerminated && !threadState.fSuspended; + return false; } @Override @@ -514,14 +509,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo // Thread case IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); if (thread != null) { - doSuspendThread(thread, rm); + doSuspend(thread, rm); return; } - // Container case + // Process case IMIContainerDMContext container = DMContexts.getAncestorOfType(context, IMIContainerDMContext.class); if (container != null) { - doSuspendContainer(container, rm); + doSuspend(container, rm); return; } @@ -530,8 +525,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo rm.done(); } - private void doSuspendThread(IMIExecutionDMContext context, final RequestMonitor rm) { - + private void doSuspend(IMIExecutionDMContext context, final RequestMonitor rm) { if (!doCanSuspend(context)) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$ @@ -542,7 +536,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo fConnection.queueCommand(fCommandFactory.createMIExecInterrupt(context), new DataRequestMonitor(getExecutor(), rm)); } - private void doSuspendContainer(IMIContainerDMContext context, final RequestMonitor rm) { + private void doSuspend(IMIContainerDMContext context, final RequestMonitor rm) { + if (!doCanSuspend(context)) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, + "Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + rm.done(); + return; + } + String groupId = context.getGroupId(); fConnection.queueCommand(fCommandFactory.createMIExecInterrupt(context, groupId), new DataRequestMonitor(getExecutor(), rm)); } @@ -554,39 +555,34 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo @Override public void canResume(IExecutionDMContext context, DataRequestMonitor rm) { if (fRunControlOperationsEnabled == false) { - rm.setData(false); - rm.done(); + rm.done(false); return; } - // Thread case - if (context instanceof IMIExecutionDMContext) { - rm.setData(doCanResume(context)); - rm.done(); - return; - } - - // Container case - if (context instanceof IContainerDMContext) { - boolean canSuspend = false; - for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) { - if (DMContexts.isAncestorOf(threadContext, context)) { - canSuspend |= doCanResume(threadContext); - } - } - rm.setData(canSuspend); - rm.done(); - return; - } - - // Default case - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$ - rm.done(); + rm.done(doCanResume(context)); } private boolean doCanResume(IExecutionDMContext context) { - MIThreadRunState threadState = fThreadRunStates.get(context); - return (threadState == null) ? false : !fTerminated && threadState.fSuspended && !threadState.fResumePending; + // Thread case + if (context instanceof IMIExecutionDMContext) { + MIThreadRunState threadState = fThreadRunStates.get(context); + return (threadState == null) ? false : !fTerminated && threadState.fSuspended && !threadState.fResumePending; + } + + // Process case + if (context instanceof IMIContainerDMContext) { + for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) { + if (DMContexts.isAncestorOf(threadContext, context)) { + if (doCanResume(threadContext)) { + return true; + } + } + } + return false; + } + + // Default case + return false; } @Override @@ -597,14 +593,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo // Thread case IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); if (thread != null) { - doResumeThread(thread, rm); + doResume(thread, rm); return; } // Container case IMIContainerDMContext container = DMContexts.getAncestorOfType(context, IMIContainerDMContext.class); if (container != null) { - doResumeContainer(container, rm); + doResume(container, rm); return; } @@ -613,8 +609,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo rm.done(); } - private void doResumeThread(IMIExecutionDMContext context, final RequestMonitor rm) { - + private void doResume(IMIExecutionDMContext context, final RequestMonitor rm) { if (!doCanResume(context)) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$ @@ -640,7 +635,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo }); } - private void doResumeContainer(IMIContainerDMContext context, final RequestMonitor rm) { + private void doResume(IMIContainerDMContext context, final RequestMonitor rm) { + if (!doCanResume(context)) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, + "Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + rm.done(); + return; + } + String groupId = context.getGroupId(); fConnection.queueCommand(fCommandFactory.createMIExecContinue(context, groupId), new DataRequestMonitor(getExecutor(), rm)); } @@ -665,8 +667,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo @Override public void canStep(final IExecutionDMContext context, StepType stepType, final DataRequestMonitor rm) { if (fRunControlOperationsEnabled == false) { - rm.setData(false); - rm.done(); + rm.done(false); return; } @@ -683,8 +684,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo @Override public void handleCompleted() { if (isSuccess() && getData() == 1) { - rm.setData(false); - rm.done(); + rm.done(false); } else { canResume(context, rm); } @@ -699,8 +699,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo } // If it's a container, then we don't want to step it - rm.setData(false); - rm.done(); + rm.done(false); } @Override @@ -710,24 +709,21 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); if (dmc == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ - rm.done(); return; } - if (!doCanResume(context)) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, + if (!doCanResume(dmc)) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot resume context", null)); //$NON-NLS-1$ - rm.done(); return; } final MIThreadRunState threadState = fThreadRunStates.get(context); if (threadState == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Given context: " + context + " can't be found.", null)); //$NON-NLS-1$ //$NON-NLS-2$ - rm.done(); return; } @@ -751,9 +747,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo IFrameDMContext topFrameDmc = stackService.createFrameDMContext(dmc, 0); cmd = fCommandFactory.createMIExecFinish(topFrameDmc); } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Cannot create context for command, stack service not available.", null)); //$NON-NLS-1$ - rm.done(); return; } break; @@ -764,9 +759,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo cmd = fCommandFactory.createMIExecNextInstruction(dmc); break; default: - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Given step type not supported", null)); //$NON-NLS-1$ - rm.done(); return; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java index 637cda00901..97d14197095 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java @@ -148,12 +148,12 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS protected void handleSuccess() { if (getData()) { if (thread != null) { - doResumeThread(thread, rm); + doResume(thread, rm); return; } if (container != null) { - doResumeContainer(container, rm); + doResume(container, rm); return; } } else { @@ -165,7 +165,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS }); } - private void doResumeThread(IMIExecutionDMContext context, final RequestMonitor rm) { + private void doResume(IMIExecutionDMContext context, final RequestMonitor rm) { final MIThreadRunState threadState = fThreadRunStates.get(context); if (threadState == null) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, @@ -184,7 +184,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS }); } - private void doResumeContainer(IMIContainerDMContext context, final RequestMonitor rm) { + private void doResume(IMIContainerDMContext context, final RequestMonitor rm) { fConnection.queueCommand(fCommandFactory.createMIExecContinue(context), new DataRequestMonitor(getExecutor(), rm)); } From 94759400896aae11394ae0cec398b53fbe09a1ba Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Mon, 16 Apr 2012 20:47:52 -0700 Subject: [PATCH 04/13] Fixed a compiler warning. --- .../cdt/internal/core/pdom/PDOMManager.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index 09a72dba2c4..a7ffd73770b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -20,7 +20,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -1206,42 +1205,41 @@ public class PDOMManager implements IWritableIndexManager, IListener { if (!deleted) { throw new IllegalArgumentException( MessageFormat.format(Messages.PDOMManager_ExistingFileCollides, - new Object[] {targetLocation}) - ); + targetLocation )); } } try { - // copy it + // Copy it. PDOM pdom= getOrCreatePDOM(cproject); pdom.acquireReadLock(); String oldID= null; try { oldID= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID); pdom.flush(); - FileChannel to = new FileOutputStream(targetLocation).getChannel(); - pdom.getDB().transferTo(to); - to.close(); + FileOutputStream stream = new FileOutputStream(targetLocation); + pdom.getDB().transferTo(stream.getChannel()); + stream.close(); } finally { pdom.releaseReadLock(); } - // overwrite internal location representations + // Overwrite internal location representations. final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter(), getLinkageFactories()); newPDOM.acquireWriteLock(); try { newPDOM.rewriteLocations(newConverter); - // ensure fragment id has a sensible value, in case callee's do not - // overwrite their own values - newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported."+oldID); //$NON-NLS-1$ + // Ensure that fragment id has a sensible value, in case callee's do not + // overwrite with their own values. + newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported." + oldID); //$NON-NLS-1$ newPDOM.close(); } finally { newPDOM.releaseWriteLock(); } - } catch (IOException ioe) { - throw new CoreException(CCorePlugin.createStatus(ioe.getMessage())); - } catch (InterruptedException ie) { - throw new CoreException(CCorePlugin.createStatus(ie.getMessage())); + } catch (IOException e) { + throw new CoreException(CCorePlugin.createStatus(e.getMessage())); + } catch (InterruptedException e) { + throw new CoreException(CCorePlugin.createStatus(e.getMessage())); } } From f3f2671d487d66ebdcd48cc5ceb4c667c815f150 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 17 Apr 2012 12:05:31 -0700 Subject: [PATCH 05/13] Fixed a typo. --- .../org/eclipse/cdt/codan/core/cxx/model/CxxModelsCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/CxxModelsCache.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/CxxModelsCache.java index bda7bb899d8..ebeee7e1130 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/CxxModelsCache.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/CxxModelsCache.java @@ -89,7 +89,7 @@ public class CxxModelsCache implements ICodanDisposable { return cfg; cfg = CxxControlFlowGraph.build(func); // TODO(Alena Laskavaia): Change to LRU. - if (cfgmap.size() > 20) { // if too many function better drop the cash + if (cfgmap.size() > 20) { // if too many function better drop the cache cfgmap.clear(); } cfgmap.put(func, cfg); From 885f6f1b7e6a2e6902435d09bd80c0811d19ca04 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 17 Apr 2012 18:15:00 -0700 Subject: [PATCH 06/13] Cosmetics. --- .../internal/core/dom/parser/ASTProblem.java | 2 +- .../internal/ui/editor/CDocumentProvider.java | 324 +++------- .../ui/editor/SemanticHighlighting.java | 3 - .../ui/editor/SemanticHighlightings.java | 610 ++---------------- 4 files changed, 149 insertions(+), 790 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java index 1c24b726ce6..ada44c0f132 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java @@ -105,9 +105,9 @@ public class ASTProblem extends ASTNode implements IASTProblem { setOffset(startNumber); setLength(endNumber-startNumber); - this.isError= isError; this.id = id; this.arg = arg; + this.isError= isError; } public ASTProblem(int id, char[] arg, boolean isError) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java index 3d7b127d12f..55c519499b8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java @@ -104,7 +104,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { */ static protected class ProblemAnnotation extends Annotation implements ICAnnotation { private static final String INDEXER_ANNOTATION_TYPE= "org.eclipse.cdt.ui.indexmarker"; //$NON-NLS-1$ - + private final ITranslationUnit fTranslationUnit; private final int fId; private final boolean fIsProblem; @@ -120,65 +120,45 @@ public class CDocumentProvider extends TextFileDocumentProvider { fArguments= isProblem() ? problem.getArguments() : null; setType(problem instanceof CoreSpellingProblem ? SpellingAnnotation.TYPE : INDEXER_ANNOTATION_TYPE); - if (problem instanceof IPersistableProblem) + if (problem instanceof IPersistableProblem) { fMarkerType= ((IPersistableProblem) problem).getMarkerType(); - else + } else { fMarkerType= null; + } } - - /* - * @see ICAnnotation#getArguments() - */ + @Override public String[] getArguments() { return fArguments; } - - /* - * @see ICAnnotation#getId() - */ + @Override public int getId() { return fId; } - - /* - * @see ICAnnotation#isProblem() - */ + @Override public boolean isProblem() { return fIsProblem; } - - /* - * @see ICAnnotation#hasOverlay() - */ + @Override public boolean hasOverlay() { return false; } - - /* - * @see ICAnnotation#getOverlay() - */ + @Override public ICAnnotation getOverlay() { return null; } - - /* - * @see ICAnnotation#addOverlaid(ICAnnotation) - */ + @Override public void addOverlaid(ICAnnotation annotation) { if (fOverlaids == null) fOverlaids= new ArrayList(1); fOverlaids.add(annotation); } - - /* - * @see ICAnnotation#removeOverlaid(ICAnnotation) - */ + @Override public void removeOverlaid(ICAnnotation annotation) { if (fOverlaids != null) { @@ -187,34 +167,25 @@ public class CDocumentProvider extends TextFileDocumentProvider { fOverlaids= null; } } - - /* - * @see ICAnnotation#getOverlaidIterator() - */ + @Override public Iterator getOverlaidIterator() { if (fOverlaids != null) return fOverlaids.iterator(); return null; } - - /* - * @see org.eclipse.cdt.internal.ui.editor.ICAnnotation#getTranslationUnit() - */ + @Override public ITranslationUnit getTranslationUnit() { return fTranslationUnit; } - /* - * @see org.eclipsecjdt.internal.ui.editor.ICAnnotation#getMarkerType() - */ @Override public String getMarkerType() { return fMarkerType; } } - + /** * Internal structure for mapping positions to some value. * The reason for this specific structure is that positions can @@ -222,22 +193,21 @@ public class CDocumentProvider extends TextFileDocumentProvider { * on hash value. */ protected static class ReverseMap { - + static class Entry { Position fPosition; Object fValue; } - + private List fList= new ArrayList(2); private int fAnchor= 0; - + public ReverseMap() { } - + public Object get(Position position) { - Entry entry; - + // behind anchor int length= fList.size(); for (int i= fAnchor; i < length; i++) { @@ -247,7 +217,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { return entry.fValue; } } - + // before anchor for (int i= 0; i < fAnchor; i++) { entry= fList.get(i); @@ -256,10 +226,10 @@ public class CDocumentProvider extends TextFileDocumentProvider { return entry.fValue; } } - + return null; } - + private int getIndex(Position position) { Entry entry; int length= fList.size(); @@ -270,7 +240,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { } return -1; } - + public void put(Position position, Object value) { int index= getIndex(position); if (index == -1) { @@ -283,13 +253,13 @@ public class CDocumentProvider extends TextFileDocumentProvider { entry.fValue= value; } } - + public void remove(Position position) { int index= getIndex(position); if (index > -1) fList.remove(index); } - + public void clear() { fList.clear(); fAnchor= 0; @@ -300,32 +270,22 @@ public class CDocumentProvider extends TextFileDocumentProvider { * A marker updater which removes problems markers with length 0. */ public static class ProblemMarkerUpdater implements IMarkerUpdater { - /** * Default constructor (executable extension). */ public ProblemMarkerUpdater() { } - /* - * @see org.eclipse.ui.texteditor.IMarkerUpdater#getAttribute() - */ @Override public String[] getAttribute() { return null; } - /* - * @see org.eclipse.ui.texteditor.IMarkerUpdater#getMarkerType() - */ @Override public String getMarkerType() { return ICModelMarker.C_MODEL_PROBLEM_MARKER; } - /* - * @see org.eclipse.ui.texteditor.IMarkerUpdater#updateMarker(org.eclipse.core.resources.IMarker, org.eclipse.jface.text.IDocument, org.eclipse.jface.text.Position) - */ @Override public boolean updateMarker(IMarker marker, IDocument document, Position position) { if (position == null) { @@ -340,37 +300,37 @@ public class CDocumentProvider extends TextFileDocumentProvider { /** * Annotation model dealing with c marker annotations and temporary problems. - * Also acts as a problem requestor for its translation unit. Initially inactive. Must be explicitly - * activated. + * Also acts as a problem requestor for its translation unit. Initially inactive. + * Must be explicitly activated. */ - protected static class TranslationUnitAnnotationModel extends ResourceMarkerAnnotationModel implements IProblemRequestor, IProblemRequestorExtension { - + protected static class TranslationUnitAnnotationModel extends ResourceMarkerAnnotationModel + implements IProblemRequestor, IProblemRequestorExtension { + private static class ProblemRequestorState { - boolean fInsideReportingSequence= false; + boolean fInsideReportingSequence; List fReportedProblems; } - + private ThreadLocal fProblemRequestorState= new ThreadLocal(); private int fStateCount= 0; - + private ITranslationUnit fTranslationUnit; private List fGeneratedAnnotations; private IProgressMonitor fProgressMonitor; - private boolean fIsActive= false; - + private boolean fIsActive; + private ReverseMap fReverseMap= new ReverseMap(); - private List fPreviouslyOverlaid= null; + private List fPreviouslyOverlaid; private List fCurrentlyOverlaid= new ArrayList(); - - + public TranslationUnitAnnotationModel(IResource resource) { super(resource); } - + public void setTranslationUnit(ITranslationUnit unit) { fTranslationUnit= unit; } - + @Override protected MarkerAnnotation createMarkerAnnotation(IMarker marker) { String markerType= MarkerUtilities.getMarkerType(marker); @@ -379,22 +339,18 @@ public class CDocumentProvider extends TextFileDocumentProvider { } return super.createMarkerAnnotation(marker); } - - - /* (non-Javadoc) - * @see org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel#createPositionFromMarker(org.eclipse.core.resources.IMarker) - */ + @Override protected Position createPositionFromMarker(IMarker marker) { int start= MarkerUtilities.getCharStart(marker); int end= MarkerUtilities.getCharEnd(marker); - + if (start > end) { end= start + end; start= end - start; end= end - start; } - + if (start == -1 && end == -1) { // marker line number is 1-based int line= MarkerUtilities.getLineNumber(marker); @@ -414,56 +370,48 @@ public class CDocumentProvider extends TextFileDocumentProvider { } } } - + if (start > -1 && end > -1) return new Position(start, end - start); - + return null; } - /* - * @see org.eclipse.jface.text.source.AnnotationModel#createAnnotationModelEvent() - */ + @Override protected AnnotationModelEvent createAnnotationModelEvent() { return new TranslationUnitAnnotationModelEvent(this, getResource()); } - + protected Position createPositionFromProblem(IProblem problem) { int start= problem.getSourceStart(); if (start < 0) return null; - + int length= problem.getSourceEnd() - problem.getSourceStart() + 1; if (length < 0) return null; return new Position(start, length); } - - /* - * @see IProblemRequestor#beginReporting() - */ + @Override public void beginReporting() { ProblemRequestorState state= fProblemRequestorState.get(); if (state == null) internalBeginReporting(false); } - - /* - * @see org.eclipse.cdt.internal.ui.text.java.IProblemRequestorExtension#beginReportingSequence() - */ + @Override public void beginReportingSequence() { ProblemRequestorState state= fProblemRequestorState.get(); if (state == null) internalBeginReporting(true); } - + /** * Sets up the infrastructure necessary for problem reporting. - * + * * @param insideReportingSequence true if this method - * call is issued from inside a reporting sequence + * call is issued from inside a reporting sequence */ private void internalBeginReporting(boolean insideReportingSequence) { if (fTranslationUnit != null) { @@ -476,10 +424,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { } } } - - /* - * @see IProblemRequestor#acceptProblem(IProblem) - */ + @Override public void acceptProblem(IProblem problem) { if (isActive()) { @@ -488,95 +433,85 @@ public class CDocumentProvider extends TextFileDocumentProvider { state.fReportedProblems.add(problem); } } - - /* - * @see IProblemRequestor#endReporting() - */ + @Override public void endReporting() { ProblemRequestorState state= fProblemRequestorState.get(); if (state != null && !state.fInsideReportingSequence) internalEndReporting(state); } - - /* - * @see org.eclipse.cdt.internal.ui.text.java.IProblemRequestorExtension#endReportingSequence() - */ + @Override public void endReportingSequence() { ProblemRequestorState state= fProblemRequestorState.get(); if (state != null && state.fInsideReportingSequence) internalEndReporting(state); } - + private void internalEndReporting(ProblemRequestorState state) { int stateCount= 0; - synchronized(getLockObject()) { - -- fStateCount; + synchronized (getLockObject()) { + --fStateCount; stateCount= fStateCount; fProblemRequestorState.set(null); } - + if (stateCount == 0 && isActive()) reportProblems(state.fReportedProblems); } - + /** * Signals the end of problem reporting. */ private void reportProblems(List reportedProblems) { if (fProgressMonitor != null && fProgressMonitor.isCanceled()) return; - + boolean temporaryProblemsChanged= false; - + synchronized (getLockObject()) { boolean isCanceled= false; - + fPreviouslyOverlaid= fCurrentlyOverlaid; fCurrentlyOverlaid= new ArrayList(); - + if (fGeneratedAnnotations.size() > 0) { temporaryProblemsChanged= true; removeAnnotations(fGeneratedAnnotations, false, true); fGeneratedAnnotations.clear(); } - - if (reportedProblems != null && reportedProblems.size() > 0) { - Iterator e= reportedProblems.iterator(); - while (e.hasNext()) { - + + if (reportedProblems != null) { + for (IProblem problem : reportedProblems) { if (fProgressMonitor != null && fProgressMonitor.isCanceled()) { isCanceled= true; break; } - - IProblem problem= e.next(); + Position position= createPositionFromProblem(problem); if (position != null) { - try { ProblemAnnotation annotation= new ProblemAnnotation(problem, fTranslationUnit); overlayMarkers(position, annotation); addAnnotation(annotation, position, false); fGeneratedAnnotations.add(annotation); - + temporaryProblemsChanged= true; } catch (BadLocationException x) { - // ignore invalid position + // Ignore invalid position } } } } - + removeMarkerOverlays(isCanceled); fPreviouslyOverlaid= null; } - + if (temporaryProblemsChanged) fireModelChanged(); } - + private void removeMarkerOverlays(boolean isCanceled) { if (isCanceled) { fCurrentlyOverlaid.addAll(fPreviouslyOverlaid); @@ -588,7 +523,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { } } } - + /** * Overlays value with problem annotation. * @param problemAnnotation @@ -601,28 +536,28 @@ public class CDocumentProvider extends TextFileDocumentProvider { fPreviouslyOverlaid.remove(annotation); fCurrentlyOverlaid.add(annotation); } - } else { } } - + private void overlayMarkers(Position position, ProblemAnnotation problemAnnotation) { Object value= getAnnotations(position); if (value instanceof List) { List list= (List) value; - for (Object element : list) + for (Object element : list) { setOverlay(element, problemAnnotation); + } } else { setOverlay(value, problemAnnotation); } } - + /** * Tells this annotation model to collect temporary problems from now on. */ private void startCollectingProblems() { fGeneratedAnnotations= new ArrayList(); } - + /** * Tells this annotation model to no longer collect temporary problems. */ @@ -631,26 +566,17 @@ public class CDocumentProvider extends TextFileDocumentProvider { removeAnnotations(fGeneratedAnnotations, true, true); fGeneratedAnnotations= null; } - - /* - * @see IProblemRequestor#isActive() - */ + @Override public boolean isActive() { return fIsActive; } - - /* - * @see IProblemRequestorExtension#setProgressMonitor(IProgressMonitor) - */ + @Override public void setProgressMonitor(IProgressMonitor monitor) { fProgressMonitor= monitor; } - - /* - * @see IProblemRequestorExtension#setIsActive(boolean) - */ + @Override public void setIsActive(boolean isActive) { if (fIsActive != isActive) { @@ -661,21 +587,18 @@ public class CDocumentProvider extends TextFileDocumentProvider { stopCollectingProblems(); } } - + private Object getAnnotations(Position position) { synchronized (getLockObject()) { return fReverseMap.get(position); } } - - /* - * @see AnnotationModel#addAnnotation(Annotation, Position, boolean) - */ + @Override @SuppressWarnings({ "unchecked" }) protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) throws BadLocationException { super.addAnnotation(annotation, position, fireModelChanged); - + synchronized (getLockObject()) { Object cached= fReverseMap.get(position); if (cached == null) { @@ -691,10 +614,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { } } } - - /* - * @see AnnotationModel#removeAllAnnotations(boolean) - */ + @Override protected void removeAllAnnotations(boolean fireModelChanged) { super.removeAllAnnotations(fireModelChanged); @@ -702,10 +622,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { fReverseMap.clear(); } } - - /* - * @see AnnotationModel#removeAnnotation(Annotation, boolean) - */ + @Override protected void removeAnnotation(Annotation annotation, boolean fireModelChanged) { Position position= getPosition(annotation); @@ -727,16 +644,12 @@ public class CDocumentProvider extends TextFileDocumentProvider { } protected static class GlobalAnnotationModelListener implements IAnnotationModelListener, IAnnotationModelListenerExtension { - private ListenerList fListenerList; - + public GlobalAnnotationModelListener() { fListenerList= new ListenerList(ListenerList.IDENTITY); } - - /** - * @see IAnnotationModelListener#modelChanged(IAnnotationModel) - */ + @Override public void modelChanged(IAnnotationModel model) { Object[] listeners= fListenerList.getListeners(); @@ -745,9 +658,6 @@ public class CDocumentProvider extends TextFileDocumentProvider { } } - /** - * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent) - */ @Override public void modelChanged(AnnotationModelEvent event) { Object[] listeners= fListenerList.getListeners(); @@ -757,16 +667,16 @@ public class CDocumentProvider extends TextFileDocumentProvider { } } } - + public void addListener(IAnnotationModelListener listener) { fListenerList.add(listener); } - + public void removeListener(IAnnotationModelListener listener) { fListenerList.remove(listener); } } - + /** Preference key for temporary problems */ private final static String HANDLE_TEMPORARY_PROBLEMS= PreferenceConstants.EDITOR_EVALUATE_TEMPORARY_PROBLEMS; @@ -775,9 +685,6 @@ public class CDocumentProvider extends TextFileDocumentProvider { /** Annotation model listener added to all created CU annotation models */ private GlobalAnnotationModelListener fGlobalAnnotationModelListener; - /** - * - */ public CDocumentProvider() { super(); IDocumentProvider parentProvider= new ExternalSearchDocumentProvider(); @@ -794,9 +701,6 @@ public class CDocumentProvider extends TextFileDocumentProvider { CUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPropertyListener); } - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#connect(java.lang.Object) - */ @Override public void connect(Object element) throws CoreException { super.connect(element); @@ -810,9 +714,8 @@ public class CDocumentProvider extends TextFileDocumentProvider { /** * Creates a translation unit from the given file. - * - * @param file - * the file from which to create the translation unit + * + * @param file the file from which to create the translation unit */ protected ITranslationUnit createTranslationUnit(IFile file) { Object element = CoreModel.getDefault().create(file); @@ -820,7 +723,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { return (ITranslationUnit) element; } if (element == null) { - // not in a source folder? + // Not in a source folder? ICProject cproject= CoreModel.getDefault().create(file.getProject()); if (cproject != null) { String contentTypeId= CoreModel.getRegistedContentTypeId(file.getProject(), file.getName()); @@ -832,25 +735,16 @@ public class CDocumentProvider extends TextFileDocumentProvider { return null; } - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createEmptyFileInfo() - */ @Override protected FileInfo createEmptyFileInfo() { return new TranslationUnitInfo(); } - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createAnnotationModel(org.eclipse.core.resources.IFile) - */ @Override protected IAnnotationModel createAnnotationModel(IFile file) { return new TranslationUnitAnnotationModel(file); } - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createFileInfo(java.lang.Object) - */ @Override protected FileInfo createFileInfo(Object element) throws CoreException { ITranslationUnit original = null; @@ -876,7 +770,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { if (original == null) { return null; } - + FileInfo info = super.createFileInfo(element); if (!(info instanceof TranslationUnitInfo)) return null; @@ -915,7 +809,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { } /** - * Try to synthesize an ITranslationUnit out of thin air. + * Tries to synthesize an ITranslationUnit out of thin air. * @param location the file system location of the file in question * @return a translation unit or null */ @@ -931,7 +825,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { } /** - * Try to synthesize an ITranslationUnit out of thin air. + * Tries to synthesize an ITranslationUnit out of thin air. * @param uri the URU of the file in question * @return a translation unit or null */ @@ -946,10 +840,6 @@ public class CDocumentProvider extends TextFileDocumentProvider { return null; } - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#disposeFileInfo(java.lang.Object, - * org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo) - */ @Override protected void disposeFileInfo(Object element, FileInfo info) { if (info instanceof TranslationUnitInfo) { @@ -1020,25 +910,17 @@ public class CDocumentProvider extends TextFileDocumentProvider { } } - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createSaveOperation(java.lang.Object, org.eclipse.jface.text.IDocument, boolean) - */ @Override protected DocumentProviderOperation createSaveOperation(final Object element, final IDocument document, final boolean overwrite) throws CoreException { final FileInfo info= getFileInfo(element); if (info instanceof TranslationUnitInfo) { return new DocumentProviderOperation() { - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor) - */ @Override protected void execute(IProgressMonitor monitor) throws CoreException { commitWorkingCopy(monitor, element, (TranslationUnitInfo) info, overwrite); } - /* - * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule() - */ + @Override public ISchedulingRule getSchedulingRule() { if (info.fElement instanceof IFileEditorInput) { @@ -1055,7 +937,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { /** * Removes trailing whitespaces from changed lines and adds newline at the end of the file, * if the last line of the file was changed. - * @throws BadLocationException + * @throws BadLocationException */ private void performSaveActions(ITextFileBuffer buffer, IProgressMonitor monitor) throws CoreException { if (shouldRemoveTrailingWhitespace() || shouldAddNewlineAtEof()) { @@ -1099,7 +981,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { return PreferenceConstants.getPreferenceStore().getBoolean( PreferenceConstants.REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES); } - + private static boolean needsChangedRegions() { return shouldRemoveTrailingWhitespace() && isLimitedRemoveTrailingWhitespace(); } @@ -1182,7 +1064,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { // } // return true; // } - + /** * Returns the preference whether handling temporary problems is enabled. */ @@ -1190,7 +1072,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); return store.getBoolean(HANDLE_TEMPORARY_PROBLEMS); } - + /** * Switches the state of problem acceptance according to the value in the preference store. */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java index 570a59fd135..a58b7463bc6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlighting.java @@ -10,7 +10,6 @@ * Anton Leherbauer (Wind River Systems) - Adapted for CDT * Markus Schorn (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.internal.ui.editor; import org.eclipse.jface.resource.ColorRegistry; @@ -26,7 +25,6 @@ import org.eclipse.cdt.ui.CUIPlugin; * @since 4.0 */ public abstract class SemanticHighlighting { - /** * @return the preference key, will be augmented by a prefix and a suffix for each preference */ @@ -126,5 +124,4 @@ public abstract class SemanticHighlighting { return rgb; return defaultRGB; } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java index 73f17530039..9f199957714 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java @@ -9,7 +9,6 @@ * IBM Corporation - initial API and implementation * Anton Leherbauer (Wind River Systems) - Adapted for CDT *******************************************************************************/ - package org.eclipse.cdt.internal.ui.editor; import org.eclipse.core.runtime.CoreException; @@ -74,117 +73,117 @@ public class SemanticHighlightings { /** * A named preference part that controls the highlighting of static fields. */ - public static final String STATIC_FIELD="staticField"; //$NON-NLS-1$ + public static final String STATIC_FIELD= "staticField"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of fields. */ - public static final String FIELD="field"; //$NON-NLS-1$ + public static final String FIELD= "field"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of method declarations. */ - public static final String METHOD_DECLARATION="methodDeclaration"; //$NON-NLS-1$ + public static final String METHOD_DECLARATION= "methodDeclaration"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of static method invocations. */ - public static final String STATIC_METHOD_INVOCATION="staticMethod"; //$NON-NLS-1$ + public static final String STATIC_METHOD_INVOCATION= "staticMethod"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of function declarations. */ - public static final String FUNCTION_DECLARATION="functionDeclaration"; //$NON-NLS-1$ + public static final String FUNCTION_DECLARATION= "functionDeclaration"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of functions. */ - public static final String FUNCTION="function"; //$NON-NLS-1$ + public static final String FUNCTION= "function"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of local variables. */ - public static final String LOCAL_VARIABLE_DECLARATION="localVariableDeclaration"; //$NON-NLS-1$ + public static final String LOCAL_VARIABLE_DECLARATION= "localVariableDeclaration"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of local variable references. */ - public static final String LOCAL_VARIABLE="localVariable"; //$NON-NLS-1$ + public static final String LOCAL_VARIABLE= "localVariable"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of global variables. */ - public static final String GLOBAL_VARIABLE="globalVariable"; //$NON-NLS-1$ + public static final String GLOBAL_VARIABLE= "globalVariable"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of parameter variables. */ - public static final String PARAMETER_VARIABLE="parameterVariable"; //$NON-NLS-1$ + public static final String PARAMETER_VARIABLE= "parameterVariable"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of template parameters. */ - public static final String TEMPLATE_PARAMETER="templateParameter"; //$NON-NLS-1$ + public static final String TEMPLATE_PARAMETER= "templateParameter"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of methods. */ - public static final String METHOD="method"; //$NON-NLS-1$ + public static final String METHOD= "method"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of classes. */ - public static final String CLASS="class"; //$NON-NLS-1$ + public static final String CLASS= "class"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of enums. */ - public static final String ENUM="enum"; //$NON-NLS-1$ + public static final String ENUM= "enum"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of macro references. */ - public static final String MACRO_REFERENCE="macroSubstitution"; //$NON-NLS-1$ + public static final String MACRO_REFERENCE= "macroSubstitution"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of macro definitions. */ - public static final String MACRO_DEFINITION="macroDefinition"; //$NON-NLS-1$ + public static final String MACRO_DEFINITION= "macroDefinition"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of typedefs. */ - public static final String TYPEDEF="typedef"; //$NON-NLS-1$ + public static final String TYPEDEF= "typedef"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of namespaces. */ - public static final String NAMESPACE="namespace"; //$NON-NLS-1$ + public static final String NAMESPACE= "namespace"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of labels. */ - public static final String LABEL="label"; //$NON-NLS-1$ + public static final String LABEL= "label"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of enumerators. */ - public static final String ENUMERATOR="enumerator"; //$NON-NLS-1$ + public static final String ENUMERATOR= "enumerator"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of problems. */ - public static final String PROBLEM="problem"; //$NON-NLS-1$ + public static final String PROBLEM= "problem"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of external SDK. */ - public static final String EXTERNAL_SDK="externalSDK"; //$NON-NLS-1$ + public static final String EXTERNAL_SDK= "externalSDK"; //$NON-NLS-1$ /** * A named preference part that controls the highlighting of operators that have been overloaded. */ - public static final String OVERLOADED_OPERATOR="overloadedOperator"; //$NON-NLS-1$ + public static final String OVERLOADED_OPERATOR= "overloadedOperator"; //$NON-NLS-1$ /** Init debugging mode */ @@ -199,63 +198,41 @@ public class SemanticHighlightings { * Semantic highlighting for static fields. */ private static final class StaticFieldHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return STATIC_FIELD; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(0, 0, 192); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_staticField; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName && name.isReference()) { return false; } @@ -272,63 +249,41 @@ public class SemanticHighlightings { * Semantic highlighting for fields. */ private static final class FieldHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return FIELD; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(0, 0, 192); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_field; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName && name.isReference()) { return false; } @@ -345,58 +300,36 @@ public class SemanticHighlightings { * Semantic highlighting for method declarations. */ private static final class MethodDeclarationHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return METHOD_DECLARATION; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_methodDeclaration; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); @@ -404,7 +337,7 @@ public class SemanticHighlightings { return false; if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (!name.isReference()) { IBinding binding= token.getBinding(); if (binding instanceof ICPPMethod) { @@ -417,7 +350,7 @@ public class SemanticHighlightings { } if (node instanceof ICPPASTFunctionDeclarator) { if (name instanceof ICPPASTQualifiedName) { - ICPPASTQualifiedName qName= (ICPPASTQualifiedName)name; + ICPPASTQualifiedName qName= (ICPPASTQualifiedName) name; IASTName[] names= qName.getNames(); if (names.length > 1) { if (names[names.length - 2].getBinding() instanceof ICPPClassType) { @@ -444,63 +377,41 @@ public class SemanticHighlightings { * Semantic highlighting for static method invocations. */ private static final class StaticMethodInvocationHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return STATIC_METHOD_INVOCATION; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_staticMethodInvocation; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName) { return false; } @@ -509,7 +420,7 @@ public class SemanticHighlightings { } IBinding binding= token.getBinding(); if (binding instanceof ICPPMethod && !(binding instanceof IProblemBinding)) { - return ((ICPPMethod)binding).isStatic(); + return ((ICPPMethod) binding).isStatic(); } } return false; @@ -520,65 +431,43 @@ public class SemanticHighlightings { * Semantic highlighting for methods. */ private static final class MethodHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return METHOD; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_method; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTImplicitName) return false; if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName && name.isReference()) { return false; } @@ -589,65 +478,42 @@ public class SemanticHighlightings { } return false; } - } /** * Semantic highlighting for function declarations. */ private static final class FunctionDeclarationHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return FUNCTION_DECLARATION; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_functionDeclaration; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); @@ -655,11 +521,10 @@ public class SemanticHighlightings { return false; if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name.isDeclaration()) { IBinding binding= token.getBinding(); - if (binding instanceof IFunction - && !(binding instanceof ICPPMethod)) { + if (binding instanceof IFunction && !(binding instanceof ICPPMethod)) { return true; } else if (binding instanceof IProblemBinding) { // try to derive from AST @@ -690,65 +555,43 @@ public class SemanticHighlightings { * Semantic highlighting for functions. */ private static final class FunctionHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return FUNCTION; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_function; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTImplicitName) return false; if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName && name.isReference()) { return false; } @@ -765,63 +608,41 @@ public class SemanticHighlightings { * Semantic highlighting for local variable declarations. */ private static final class LocalVariableDeclarationHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return LOCAL_VARIABLE_DECLARATION; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(128, 0, 0); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_localVariableDeclaration; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name.isDeclaration()) { IBinding binding= token.getBinding(); if (binding instanceof IVariable @@ -841,70 +662,47 @@ public class SemanticHighlightings { } return false; } - -} + } /** * Semantic highlighting for local variables. */ private static final class LocalVariableHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return LOCAL_VARIABLE; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_localVariable; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name.isReference()) { IBinding binding= token.getBinding(); if (binding instanceof IVariable @@ -940,69 +738,47 @@ public class SemanticHighlightings { } return false; } -} + } /** * Semantic highlighting for global variables. */ private static final class GlobalVariableHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return GLOBAL_VARIABLE; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_globalVariable; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName) { return false; } @@ -1024,65 +800,42 @@ public class SemanticHighlightings { } return false; } - } /** * Semantic highlighting for parameter variables. */ private static final class ParameterVariableHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return PARAMETER_VARIABLE; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_parameterVariable; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IBinding binding= token.getBinding(); @@ -1097,58 +850,36 @@ public class SemanticHighlightings { * Semantic highlighting for template parameters. */ private static final class TemplateParameterHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return TEMPLATE_PARAMETER; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(100, 70, 50); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_templateParameter; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); @@ -1166,58 +897,36 @@ public class SemanticHighlightings { * Semantic highlighting for classes. */ private static final class ClassHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return CLASS; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(0, 80, 50); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_classes; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); @@ -1238,58 +947,36 @@ public class SemanticHighlightings { * Semantic highlighting for enums. */ private static final class EnumHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return ENUM; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(100, 70, 50); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_enums; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); @@ -1307,58 +994,36 @@ public class SemanticHighlightings { * Semantic highlighting for macro references. */ private static final class MacroReferenceHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return MACRO_REFERENCE; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_macroSubstitution; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IBinding binding= token.getBinding(); @@ -1376,58 +1041,36 @@ public class SemanticHighlightings { * Semantic highlighting for macro definitions. */ private static final class MacroDefinitionHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return MACRO_DEFINITION; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_macroDefintion; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IBinding binding= token.getBinding(); @@ -1445,63 +1088,41 @@ public class SemanticHighlightings { * Semantic highlighting for typedefs. */ private static final class TypedefHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return TYPEDEF; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(0, 80, 50); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_typeDef; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName) { return false; } @@ -1518,58 +1139,36 @@ public class SemanticHighlightings { * Semantic highlighting for namespaces. */ private static final class NamespaceHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return NAMESPACE; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_namespace; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IBinding binding= token.getBinding(); @@ -1584,58 +1183,36 @@ public class SemanticHighlightings { * Semantic highlighting for labels. */ private static final class LabelHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return LABEL; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return RGB_BLACK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_label; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IBinding binding= token.getBinding(); @@ -1650,63 +1227,41 @@ public class SemanticHighlightings { * Semantic highlighting for enumerators. */ private static final class EnumeratorHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return ENUMERATOR; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(0, 0, 192); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_enumerator; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName) { return false; } @@ -1723,66 +1278,41 @@ public class SemanticHighlightings { * Semantic highlighting for problems. */ private static final class ProblemHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return PROBLEM; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(224, 0, 0); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isStrikethroughByDefault() - */ @Override public boolean isStrikethroughByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_problem; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); @@ -1801,71 +1331,46 @@ public class SemanticHighlightings { * Semantic highlighting for external SDK references. */ private static final class ExternalSDKHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return EXTERNAL_SDK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(100, 40, 128); } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isStrikethroughByDefault() - */ @Override public boolean isStrikethroughByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return true; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_externalSDK; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); if (node instanceof IASTName) { - IASTName name= (IASTName)node; + IASTName name= (IASTName) node; if (name instanceof ICPPASTQualifiedName) { return false; } @@ -1915,69 +1420,46 @@ public class SemanticHighlightings { * Semantic highlighting for functions. */ private static final class OverloadedOperatorHighlighting extends SemanticHighlighting { - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getPreferenceKey() - */ @Override public String getPreferenceKey() { return OVERLOADED_OPERATOR; } - @Override public boolean requiresImplicitNames() { return true; } - - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultDefaultTextColor() - */ @Override public RGB getDefaultDefaultTextColor() { return new RGB(200, 100, 0); // orange } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDefaultTextStyleBold() - */ @Override public boolean isBoldByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isItalicByDefault() - */ @Override public boolean isItalicByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#isEnabledByDefault() - */ @Override public boolean isEnabledByDefault() { return false; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#getDisplayName() - */ @Override public String getDisplayName() { return CEditorMessages.SemanticHighlighting_overloadedOperators; } - /* - * @see org.eclipse.cdt.internal.ui.editor.SemanticHighlighting#consumes(org.eclipse.cdt.internal.ui.editor.SemanticToken) - */ @Override public boolean consumes(SemanticToken token) { IASTNode node = token.getNode(); - // so far we only have implicit names for overloaded operators and destructors, so this works + // So far we only have implicit names for overloaded operators and destructors, + // so this works. if (node instanceof IASTImplicitName) { IASTImplicitName name = (IASTImplicitName) node; if (name.isReference() && name.isOperator()) { @@ -2159,16 +1641,14 @@ public class SemanticHighlightings { return false; } SemanticHighlighting[] highlightings= getSemanticHighlightings(); - boolean enable= false; for (SemanticHighlighting highlighting : highlightings) { String enabledKey= getEnabledPreferenceKey(highlighting); if (store.getBoolean(enabledKey)) { - enable= true; - break; + return true; } } - return enable; + return false; } /** From e7ef578e94479290ab1a9b593a957f4a067e2dc8 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 17 Apr 2012 19:53:05 -0700 Subject: [PATCH 07/13] Bug 377045 - Bogus transient errors in C/C++ editor soon after Eclipse startup. --- .../cxx/model/AbstractIndexAstChecker.java | 25 ++++++++++++------- .../index/tests/EmptyIndexFragment.java | 5 ++++ .../internal/core/model/TranslationUnit.java | 4 ++- .../cdt/core/dom/ast/IASTTranslationUnit.java | 10 +++++++- .../org/eclipse/cdt/core/index/IIndex.java | 7 ++++++ .../core/dom/parser/ASTTranslationUnit.java | 10 ++++++++ .../cdt/internal/core/index/CIndex.java | 9 +++++++ .../cdt/internal/core/index/EmptyCIndex.java | 6 ++++- .../internal/core/index/IIndexFragment.java | 6 +++++ .../eclipse/cdt/internal/core/pdom/PDOM.java | 5 ++++ .../cdt/internal/core/pdom/PDOMProxy.java | 6 +++++ .../internal/ui/editor/CDocumentProvider.java | 14 ++++++++++- .../ui/editor/SemanticHighlightings.java | 4 +++ 13 files changed, 98 insertions(+), 13 deletions(-) diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java index 6f306b23af3..64b5fcc8ddd 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2011 Alena Laskavaia + * Copyright (c) 2009, 2012 Alena Laskavaia * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -70,10 +70,14 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem } try { - IASTTranslationUnit ast = modelCache.getAST(); - if (ast != null) { - synchronized (ast) { - processAst(ast); + // Run the checker only if the index is fully initialized. Otherwise it may produce + // false positives. + if (modelCache.getIndex().isFullyInitialized()) { + IASTTranslationUnit ast = modelCache.getAST(); + if (ast != null) { + synchronized (ast) { + processAst(ast); + } } } } catch (CoreException e) { @@ -83,16 +87,19 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem } } - /* - * (non-Javadoc) - * + /* (non-Javadoc) * @see IRunnableInEditorChecker#processModel(Object, ICheckerInvocationContext) */ @Override public synchronized void processModel(Object model, ICheckerInvocationContext context) { if (model instanceof IASTTranslationUnit) { - setContext(context); IASTTranslationUnit ast = (IASTTranslationUnit) model; + // Run the checker only if the index was fully initialized when the file was parsed. + // Otherwise the checker may produce false positives. + if (ast.isBasedOnIncompleteIndex()) + return; + + setContext(context); synchronized (context) { modelCache = context.get(CxxModelsCache.class); if (modelCache == null) { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java index f2bc149c12e..0c638a1740a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java @@ -201,4 +201,9 @@ public class EmptyIndexFragment implements IIndexFragment { public IIndexScope[] getInlineNamespaces() { return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY; } + + @Override + public boolean isFullyInitialized() { + return true; + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index 3f74ba7243b..8016d285b12 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 QNX Software Systems and others. + * Copyright (c) 2000, 2012 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -817,6 +817,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit { } public IASTTranslationUnit getAST(IIndex index, int style, IProgressMonitor monitor) throws CoreException { + boolean incompleteIndex = index != null && !index.isFullyInitialized(); IIndexFile[] contextToHeader = getContextToHeader(index, style); ITranslationUnit configureWith = getConfigureWith(contextToHeader); if (configureWith == this) @@ -860,6 +861,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit { ASTTranslationUnit ast = (ASTTranslationUnit) ((AbstractLanguage) language).getASTTranslationUnit( fileContent, scanInfo, crf, index, options, log); ast.setOriginatingTranslationUnit(this); + ast.setBasedOnIncompleteIndex(incompleteIndex); return ast; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java index b7bc864054e..36db4a9af0e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2011 IBM Corporation and others. + * Copyright (c) 2004, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * Doug Schaefer (IBM) - Initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -347,6 +348,13 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi */ public ITranslationUnit getOriginatingTranslationUnit(); + /** + * Returns {@code true} if the index was not fully initialized when the code of the translation + * unit was parsed. + * @since 5.4 + */ + boolean isBasedOnIncompleteIndex(); + /** * @since 5.4 * @noreference This method is not intended to be referenced by clients. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java index 2f868eb12e3..283652b41fe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java @@ -445,4 +445,11 @@ public interface IIndex { * @since 5.3 */ public IScope[] getInlineNamespaces() throws CoreException; + + /** + * Returns {@code true} if the index is fully initialized. An index may not be fully initialized + * during Eclipse startup, or soon after adding a new project to the workspace. + * @since 5.4 + */ + public boolean isFullyInitialized(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java index 8bced17fc9f..fe788c55505 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java @@ -80,6 +80,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat private SizeofCalculator fSizeofCalculator; /** The semaphore controlling exclusive access to the AST. */ private final Semaphore fSemaphore= new Semaphore(1); + private boolean fBasedOnIncompleteIndex; @Override public final IASTTranslationUnit getTranslationUnit() { @@ -341,6 +342,15 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat fForContentAssist= forContentAssist; } + @Override + public boolean isBasedOnIncompleteIndex() { + return fBasedOnIncompleteIndex; + } + + public void setBasedOnIncompleteIndex(boolean basedOnIncompleteIndex) { + fBasedOnIncompleteIndex = basedOnIncompleteIndex; + } + @Override public void skippedFile(int offset, InternalFileContent fileContent) { if (fIndexFileSet != null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java index 7374440818d..1fbc93e4b55 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java @@ -781,6 +781,15 @@ public class CIndex implements IIndex { return result; } + @Override + public boolean isFullyInitialized() { + for (IIndexFragment fragment : fFragments) { + if (!fragment.isFullyInitialized()) + return false; + } + return true; + } + /** * A key used to uniquely identify an IIndexFragmentName object. Uniqueness is guaranteed only * for names corresponding to the same binding. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java index 383217ae74c..503ede13120 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java @@ -12,7 +12,6 @@ * Sergey Prigogin (Google) * Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion) *******************************************************************************/ - package org.eclipse.cdt.internal.core.index; import java.util.regex.Pattern; @@ -204,4 +203,9 @@ final public class EmptyCIndex implements IIndex { public IScope[] getInlineNamespaces() { return new IScope[0]; } + + @Override + public boolean isFullyInitialized() { + return true; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java index bc7558d648a..2b2ac26362f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java @@ -349,4 +349,10 @@ public interface IIndexFragment { * @throws CoreException */ IIndexScope[] getInlineNamespaces() throws CoreException; + + /** + * Returns {@code true} if the index fragment is fully initialized. An fragment may not be fully + * initialized during Eclipse startup, or soon after adding a new project to the workspace. + */ + boolean isFullyInitialized(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index c0e9f1fede2..b15b330d85b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -1650,4 +1650,9 @@ public class PDOM extends PlatformObject implements IPDOM { } return linkage.getInlineNamespaces(); } + + @Override + public boolean isFullyInitialized() { + return true; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java index 1607aae69d8..20f4d820d0a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java @@ -350,4 +350,10 @@ public class PDOMProxy implements IPDOM { return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY; } + + + @Override + public synchronized boolean isFullyInitialized() { + return fDelegate != null; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java index 55c519499b8..02fc42d18e8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java @@ -69,6 +69,7 @@ import org.eclipse.ui.texteditor.MarkerUtilities; import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel; import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.model.ICProject; @@ -429,11 +430,22 @@ public class CDocumentProvider extends TextFileDocumentProvider { public void acceptProblem(IProblem problem) { if (isActive()) { ProblemRequestorState state= fProblemRequestorState.get(); - if (state != null) + if (state != null && isReliable(problem)) { state.fReportedProblems.add(problem); + } } } + /** + * A problem is not considered reliable if it belongs to an unreliable AST. + */ + private static boolean isReliable(IProblem problem) { + if (problem instanceof IASTNode) { + return !((IASTNode) problem).getTranslationUnit().isBasedOnIncompleteIndex(); + } + return true; + } + @Override public void endReporting() { ProblemRequestorState state= fProblemRequestorState.get(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java index 9f199957714..1fd6bbada24 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java @@ -1316,6 +1316,10 @@ public class SemanticHighlightings { @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); + if (node.getTranslationUnit().isBasedOnIncompleteIndex()) { + // Do not highlight problems is the AST is unreliable. + return false; + } if (node instanceof IASTProblem) { return true; } From 83cf5dc8303da5df560bde6ebb602b1e5cc59fb8 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 17 Apr 2012 20:11:24 -0700 Subject: [PATCH 08/13] Cosmetics. --- .../eclipse/cdt/internal/core/pdom/PDOMManager.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index a7ffd73770b..5dd7d221db5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -984,7 +984,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { Job notify= new Job(Messages.PDOMManager_notifyJob_label) { @Override protected IStatus run(IProgressMonitor monitor) { - while(true) { + while (true) { final Runnable r; synchronized (fChangeEvents) { if (fChangeEvents.isEmpty()) { @@ -1027,11 +1027,12 @@ public class PDOMManager implements IWritableIndexManager, IListener { Object[] listeners= fStateListeners.getListeners(); for (Object listener2 : listeners) { final IIndexerStateListener listener = (IIndexerStateListener) listener2; - SafeRunner.run(new ISafeRunnable(){ + SafeRunner.run(new ISafeRunnable() { @Override public void handleException(Throwable exception) { CCorePlugin.log(exception); } + @Override public void run() throws Exception { listener.indexChanged(fIndexerStateEvent); @@ -1064,11 +1065,12 @@ public class PDOMManager implements IWritableIndexManager, IListener { Object[] listeners= fChangeListeners.getListeners(); for (Object listener2 : listeners) { final IIndexChangeListener listener = (IIndexChangeListener) listener2; - SafeRunner.run(new ISafeRunnable(){ + SafeRunner.run(new ISafeRunnable() { @Override public void handleException(Throwable exception) { CCorePlugin.log(exception); } + @Override public void run() throws Exception { listener.indexChanged(fIndexChangeEvent); @@ -1433,11 +1435,12 @@ public class PDOMManager implements IWritableIndexManager, IListener { @Override public void run() { for (final IndexerSetupParticipant p : participants) { - SafeRunner.run(new ISafeRunnable(){ + SafeRunner.run(new ISafeRunnable() { @Override public void handleException(Throwable exception) { CCorePlugin.log(exception); } + @Override public void run() throws Exception { p.onIndexerSetup(cproject); From f16f0dbe483fd8fe1b2c5ab343d03201bfcccbf9 Mon Sep 17 00:00:00 2001 From: Anton Gorenkov Date: Tue, 17 Apr 2012 23:50:07 -0400 Subject: [PATCH 09/13] Bug 210366 - CDT should have Unit Testing and Component Testing like JDT --- pom.xml | 8 + releng/org.eclipse.cdt.repo/category.xml | 6 + .../.classpath | 7 + .../.project | 34 + .../.settings/org.eclipse.jdt.core.prefs | 82 ++ .../META-INF/MANIFEST.MF | 13 + .../about.html | 24 + .../build.properties | 21 + .../plugin.properties | 15 + .../plugin.xml | 13 + .../org.eclipse.cdt.testsrunner.boost/pom.xml | 17 + .../boost/BoostTestsRunnerMessages.java | 30 + .../boost/BoostTestsRunnerMessages.properties | 16 + .../boost/BoostTestsRunnerPlugin.java | 67 ++ .../boost/BoostTestsRunnerProvider.java | 113 +++ .../internal/boost/BoostXmlLogHandler.java | 229 ++++++ .../.project | 17 + .../build.properties | 16 + .../eclipse_update_120.jpg | Bin 0 -> 21695 bytes .../epl-v10.html | 328 ++++++++ .../feature.properties | 168 +++++ .../feature.xml | 52 ++ .../license.html | 108 +++ .../pom.xml | 18 + .../.classpath | 7 + .../.project | 34 + .../.settings/org.eclipse.jdt.core.prefs | 82 ++ .../META-INF/MANIFEST.MF | 13 + .../about.html | 24 + .../build.properties | 21 + .../plugin.properties | 15 + .../plugin.xml | 16 + .../org.eclipse.cdt.testsrunner.gtest/pom.xml | 17 + .../gtest/GoogleTestsRunnerMessages.java | 35 + .../GoogleTestsRunnerMessages.properties | 21 + .../gtest/GoogleTestsRunnerPlugin.java | 67 ++ .../gtest/GoogleTestsRunnerProvider.java | 97 +++ .../internal/gtest/OutputHandler.java | 645 ++++++++++++++++ .../.classpath | 7 + .../.project | 34 + .../.settings/org.eclipse.jdt.core.prefs | 82 ++ .../META-INF/MANIFEST.MF | 13 + .../about.html | 24 + .../build.properties | 21 + .../plugin.properties | 15 + .../plugin.xml | 17 + .../pom.xml | 17 + .../qttest/QtTestsRunnerMessages.java | 37 + .../qttest/QtTestsRunnerMessages.properties | 23 + .../internal/qttest/QtTestsRunnerPlugin.java | 66 ++ .../qttest/QtTestsRunnerProvider.java | 129 ++++ .../internal/qttest/QtXmlLogHandler.java | 399 ++++++++++ .../.project | 17 + .../build.properties | 5 + .../eclipse_update_120.jpg | Bin 0 -> 21695 bytes .../epl-v10.html | 328 ++++++++ .../feature.properties | 168 +++++ .../feature.xml | 51 ++ .../license.html | 108 +++ .../pom.xml | 18 + .../.classpath | 7 + .../org.eclipse.cdt.testsrunner.test/.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 82 ++ .../META-INF/MANIFEST.MF | 16 + .../OSGI-INF/l10n/bundle.properties | 13 + .../about.html | 24 + .../build.properties | 20 + .../org.eclipse.cdt.testsrunner.test/pom.xml | 42 ++ ...estModelManagerBaseReorderingTestCase.java | 123 +++ ...stModelManagerCasesReorderingTestCase.java | 40 + ...tModelManagerSuitesReorderingTestCase.java | 39 + .../testsrunner/test/TestsRunnerSuite.java | 55 ++ .../test/TestsRunnerTestActivator.java | 48 ++ .../testsrunners/BaseTestCase.java | 99 +++ .../testsrunners/BoostTestCase.java | 481 ++++++++++++ .../testsrunners/GoogleTestCase.java | 698 ++++++++++++++++++ .../testsrunners/MockTestModelUpdater.java | 221 ++++++ .../testsrunner/testsrunners/QtTestCase.java | 693 +++++++++++++++++ .../org.eclipse.cdt.testsrunner.test/test.xml | 56 ++ .../org.eclipse.cdt.testsrunner/.classpath | 7 + .../org.eclipse.cdt.testsrunner/.project | 34 + .../.settings/org.eclipse.jdt.core.prefs | 82 ++ .../META-INF/MANIFEST.MF | 37 + .../org.eclipse.cdt.testsrunner/about.html | 24 + .../build.properties | 23 + .../icons/dlcl16/history_list.gif | Bin 0 -> 225 bytes .../icons/dlcl16/orientation_auto.gif | Bin 0 -> 338 bytes .../icons/dlcl16/orientation_horizontal.gif | Bin 0 -> 354 bytes .../icons/dlcl16/orientation_vertical.gif | Bin 0 -> 219 bytes .../icons/dlcl16/rerun.gif | Bin 0 -> 580 bytes .../icons/dlcl16/scroll_lock.gif | Bin 0 -> 588 bytes .../icons/dlcl16/show_next.gif | Bin 0 -> 204 bytes .../icons/dlcl16/show_previous.gif | Bin 0 -> 152 bytes .../icons/dlcl16/sort.gif | Bin 0 -> 137 bytes .../icons/dlcl16/stop.gif | Bin 0 -> 152 bytes .../icons/elcl16/history_list.gif | Bin 0 -> 586 bytes .../icons/elcl16/orientation_auto.gif | Bin 0 -> 358 bytes .../icons/elcl16/orientation_horizontal.gif | Bin 0 -> 374 bytes .../icons/elcl16/orientation_vertical.gif | Bin 0 -> 352 bytes .../icons/elcl16/rerun.gif | Bin 0 -> 590 bytes .../icons/elcl16/scroll_lock.gif | Bin 0 -> 626 bytes .../icons/elcl16/show_next.gif | Bin 0 -> 332 bytes .../icons/elcl16/show_previous.gif | Bin 0 -> 323 bytes .../icons/elcl16/show_tests_hierarchy.gif | Bin 0 -> 101 bytes .../icons/elcl16/sort.gif | Bin 0 -> 157 bytes .../icons/elcl16/stop.gif | Bin 0 -> 215 bytes .../icons/eview16/cppunit.gif | Bin 0 -> 219 bytes .../icons/obj16/show_failed_only.gif | Bin 0 -> 163 bytes .../icons/obj16/test_aborted.gif | Bin 0 -> 374 bytes .../icons/obj16/test_failed.gif | Bin 0 -> 374 bytes .../icons/obj16/test_notrun.gif | Bin 0 -> 362 bytes .../icons/obj16/test_passed.gif | Bin 0 -> 380 bytes .../icons/obj16/test_run.gif | Bin 0 -> 594 bytes .../icons/obj16/test_skipped.gif | Bin 0 -> 365 bytes .../icons/obj16/tsuite_aborted.gif | Bin 0 -> 376 bytes .../icons/obj16/tsuite_failed.gif | Bin 0 -> 376 bytes .../icons/obj16/tsuite_notrun.gif | Bin 0 -> 358 bytes .../icons/obj16/tsuite_passed.gif | Bin 0 -> 382 bytes .../icons/obj16/tsuite_run.gif | Bin 0 -> 589 bytes .../icons/ovr16/aborted_counter.gif | Bin 0 -> 82 bytes .../icons/ovr16/failed_counter.gif | Bin 0 -> 82 bytes .../plugin.properties | 30 + .../org.eclipse.cdt.testsrunner/plugin.xml | 255 +++++++ .../org.eclipse.cdt.testsrunner/pom.xml | 17 + .../schema/TestsRunner.exsd | 178 +++++ .../internal/TestsRunnerPlugin.java | 239 ++++++ .../launcher/CdiRunTestsLaunchDelegate.java | 26 + .../DsfGdbRunTestsLaunchDelegate.java | 26 + .../ITestsLaunchConfigurationConstants.java | 36 + .../internal/launcher/LauncherMessages.java | 26 + .../launcher/LauncherMessages.properties | 12 + .../internal/launcher/ProcessWrapper.java | 115 +++ .../launcher/TestingProcessFactory.java | 111 +++ .../launcher/TestsRunnerProviderInfo.java | 167 +++++ .../launcher/TestsRunnerProvidersManager.java | 80 ++ .../ITestingSessionsManagerListener.java | 30 + .../internal/model/ModelMessages.java | 28 + .../internal/model/ModelMessages.properties | 14 + .../testsrunner/internal/model/TestCase.java | 102 +++ .../testsrunner/internal/model/TestItem.java | 56 ++ .../internal/model/TestLocation.java | 41 + .../internal/model/TestMessage.java | 57 ++ .../internal/model/TestModelManager.java | 480 ++++++++++++ .../testsrunner/internal/model/TestSuite.java | 85 +++ .../internal/model/TestingSession.java | 280 +++++++ .../model/TestingSessionsManager.java | 215 ++++++ .../internal/ui/launcher/CTestingTab.java | 200 +++++ .../launcher/EmptyConfigurationTabGroup.java | 29 + .../ui/launcher/UILauncherMessages.java | 29 + .../ui/launcher/UILauncherMessages.properties | 15 + .../internal/ui/view/CounterPanel.java | 147 ++++ .../internal/ui/view/DummyUISession.java | 85 +++ .../internal/ui/view/MessagesViewer.java | 573 ++++++++++++++ .../internal/ui/view/ProgressBar.java | 183 +++++ .../internal/ui/view/ProgressCountPanel.java | 87 +++ .../internal/ui/view/ResultsPanel.java | 245 ++++++ .../internal/ui/view/ResultsView.java | 366 +++++++++ .../internal/ui/view/TestPathUtils.java | 115 +++ .../ui/view/TestsHierarchyViewer.java | 554 ++++++++++++++ .../internal/ui/view/UIUpdater.java | 517 +++++++++++++ .../internal/ui/view/UIViewMessages.java | 36 + .../ui/view/UIViewMessages.properties | 22 + .../ui/view/actions/ActionsMessages.java | 77 ++ .../view/actions/ActionsMessages.properties | 63 ++ .../actions/CopySelectedMessagesAction.java | 65 ++ .../view/actions/CopySelectedTestsAction.java | 65 ++ .../view/actions/HistoryDropDownAction.java | 448 +++++++++++ .../actions/MessageLevelFilterAction.java | 58 ++ .../view/actions/MessagesOrderingAction.java | 42 ++ .../ui/view/actions/OpenInEditorAction.java | 181 +++++ .../view/actions/RedebugSelectedAction.java | 36 + .../view/actions/RelaunchSelectedAction.java | 96 +++ .../internal/ui/view/actions/RerunAction.java | 50 ++ .../ui/view/actions/RerunSelectedAction.java | 36 + .../ui/view/actions/ScrollLockAction.java | 41 + .../ui/view/actions/ShowFailedOnlyAction.java | 40 + .../view/actions/ShowFileNameOnlyAction.java | 38 + .../view/actions/ShowNextFailureAction.java | 40 + .../actions/ShowPreviousFailureAction.java | 40 + .../actions/ShowTestsInHierarchyAction.java | 40 + .../ui/view/actions/ShowTimeAction.java | 37 + .../internal/ui/view/actions/StopAction.java | 46 ++ .../TestsHierarchyCollapseAllAction.java | 37 + .../TestsHierarchyExpandAllAction.java | 37 + .../view/actions/ToggleOrientationAction.java | 60 ++ .../launcher/BaseTestsLaunchDelegate.java | 255 +++++++ .../launcher/ITestsRunnerConstants.java | 40 + .../launcher/ITestsRunnerProvider.java | 54 ++ .../launcher/ITestsRunnerProviderInfo.java | 68 ++ .../cdt/testsrunner/model/IModelVisitor.java | 33 + .../cdt/testsrunner/model/ITestCase.java | 31 + .../cdt/testsrunner/model/ITestItem.java | 95 +++ .../cdt/testsrunner/model/ITestLocation.java | 35 + .../cdt/testsrunner/model/ITestMessage.java | 72 ++ .../testsrunner/model/ITestModelAccessor.java | 52 ++ .../testsrunner/model/ITestModelUpdater.java | 94 +++ .../cdt/testsrunner/model/ITestSuite.java | 22 + .../testsrunner/model/ITestingSession.java | 135 ++++ .../model/ITestingSessionListener.java | 66 ++ .../cdt/testsrunner/model/ModelMessages.java | 30 + .../model/ModelMessages.properties | 16 + .../testsrunner/model/TestingException.java | 28 + 202 files changed, 15775 insertions(+) create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/.classpath create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/.settings/org.eclipse.jdt.core.prefs create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/META-INF/MANIFEST.MF create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/about.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerPlugin.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerProvider.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostXmlLogHandler.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/eclipse_update_120.jpg create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/epl-v10.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/license.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/eclipse_update_120.jpg create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/epl-v10.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/.classpath create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/about.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/test.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/.classpath create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/about.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/history_list.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_auto.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_horizontal.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_vertical.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/rerun.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/scroll_lock.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_next.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_previous.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/sort.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/stop.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/history_list.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_auto.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_horizontal.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_vertical.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/rerun.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/scroll_lock.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_next.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_previous.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_tests_hierarchy.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/sort.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/stop.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/eview16/cppunit.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/show_failed_only.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_aborted.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_failed.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_notrun.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_passed.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_run.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_skipped.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_aborted.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_failed.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_notrun.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_passed.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_run.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/aborted_counter.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/failed_counter.gif create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/plugin.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/plugin.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessageLevelFilterAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessagesOrderingAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/OpenInEditorAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RedebugSelectedAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RelaunchSelectedAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunSelectedAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ScrollLockAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFailedOnlyAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFileNameOnlyAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowNextFailureAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowPreviousFailureAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTestsInHierarchyAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTimeAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/StopAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyCollapseAllAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyExpandAllAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ToggleOrientationAction.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/BaseTestsLaunchDelegate.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerConstants.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProvider.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProviderInfo.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/IModelVisitor.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestCase.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestItem.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestLocation.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestMessage.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelAccessor.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelUpdater.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestSuite.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSession.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSessionListener.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/TestingException.java diff --git a/pom.xml b/pom.xml index dd54c310b6c..1ab4aa810e0 100644 --- a/pom.xml +++ b/pom.xml @@ -171,6 +171,14 @@ build/org.eclipse.cdt.autotools.source-feature build/org.eclipse.linuxtools.cdt.autotools.core + testsrunner/org.eclipse.cdt.testsrunner + testsrunner/org.eclipse.cdt.testsrunner.boost + testsrunner/org.eclipse.cdt.testsrunner.gtest + testsrunner/org.eclipse.cdt.testsrunner.qttest + testsrunner/org.eclipse.cdt.testsrunner.test + testsrunner/org.eclipse.cdt.testsrunner.feature + testsrunner/org.eclipse.cdt.testsrunner.source.feature + + + + + + +
+ +

Eclipse Public License - v 1.0 +

+ +

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER +THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, +REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE +OF THIS AGREEMENT.

+ +

1. DEFINITIONS

+ +

"Contribution" means:

+ +

a) +in the case of the initial Contributor, the initial code and documentation +distributed under this Agreement, and
+b) in the case of each subsequent Contributor:

+ +

i) +changes to the Program, and

+ +

ii) +additions to the Program;

+ +

where +such changes and/or additions to the Program originate from and are distributed +by that particular Contributor. A Contribution 'originates' from a Contributor +if it was added to the Program by such Contributor itself or anyone acting on +such Contributor's behalf. Contributions do not include additions to the +Program which: (i) are separate modules of software distributed in conjunction +with the Program under their own license agreement, and (ii) are not derivative +works of the Program.

+ +

"Contributor" means any person or +entity that distributes the Program.

+ +

"Licensed Patents " mean patent +claims licensable by a Contributor which are necessarily infringed by the use +or sale of its Contribution alone or when combined with the Program.

+ +

"Program" means the Contributions +distributed in accordance with this Agreement.

+ +

"Recipient" means anyone who +receives the Program under this Agreement, including all Contributors.

+ +

2. GRANT OF RIGHTS

+ +

a) +Subject to the terms of this Agreement, each Contributor hereby grants Recipient +a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly +display, publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and object code +form.

+ +

b) +Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free +patent license under Licensed Patents to make, use, sell, offer to sell, import +and otherwise transfer the Contribution of such Contributor, if any, in source +code and object code form. This patent license shall apply to the combination +of the Contribution and the Program if, at the time the Contribution is added +by the Contributor, such addition of the Contribution causes such combination +to be covered by the Licensed Patents. The patent license shall not apply to +any other combinations which include the Contribution. No hardware per se is +licensed hereunder.

+ +

c) +Recipient understands that although each Contributor grants the licenses to its +Contributions set forth herein, no assurances are provided by any Contributor +that the Program does not infringe the patent or other intellectual property +rights of any other entity. Each Contributor disclaims any liability to Recipient +for claims brought by any other entity based on infringement of intellectual +property rights or otherwise. As a condition to exercising the rights and +licenses granted hereunder, each Recipient hereby assumes sole responsibility +to secure any other intellectual property rights needed, if any. For example, +if a third party patent license is required to allow Recipient to distribute +the Program, it is Recipient's responsibility to acquire that license before +distributing the Program.

+ +

d) +Each Contributor represents that to its knowledge it has sufficient copyright +rights in its Contribution, if any, to grant the copyright license set forth in +this Agreement.

+ +

3. REQUIREMENTS

+ +

A Contributor may choose to distribute the +Program in object code form under its own license agreement, provided that: +

+ +

a) +it complies with the terms and conditions of this Agreement; and

+ +

b) +its license agreement:

+ +

i) +effectively disclaims on behalf of all Contributors all warranties and +conditions, express and implied, including warranties or conditions of title +and non-infringement, and implied warranties or conditions of merchantability +and fitness for a particular purpose;

+ +

ii) +effectively excludes on behalf of all Contributors all liability for damages, +including direct, indirect, special, incidental and consequential damages, such +as lost profits;

+ +

iii) +states that any provisions which differ from this Agreement are offered by that +Contributor alone and not by any other party; and

+ +

iv) +states that source code for the Program is available from such Contributor, and +informs licensees how to obtain it in a reasonable manner on or through a +medium customarily used for software exchange.

+ +

When the Program is made available in source +code form:

+ +

a) +it must be made available under this Agreement; and

+ +

b) a +copy of this Agreement must be included with each copy of the Program.

+ +

Contributors may not remove or alter any +copyright notices contained within the Program.

+ +

Each Contributor must identify itself as the +originator of its Contribution, if any, in a manner that reasonably allows +subsequent Recipients to identify the originator of the Contribution.

+ +

4. COMMERCIAL DISTRIBUTION

+ +

Commercial distributors of software may +accept certain responsibilities with respect to end users, business partners +and the like. While this license is intended to facilitate the commercial use +of the Program, the Contributor who includes the Program in a commercial +product offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes the +Program in a commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages and +costs (collectively "Losses") arising from claims, lawsuits and other +legal actions brought by a third party against the Indemnified Contributor to +the extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor +to control, and cooperate with the Commercial Contributor in, the defense and +any related settlement negotiations. The Indemnified Contributor may participate +in any such claim at its own expense.

+ +

For example, a Contributor might include the +Program in a commercial product offering, Product X. That Contributor is then a +Commercial Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance claims and +warranties are such Commercial Contributor's responsibility alone. Under this +section, the Commercial Contributor would have to defend claims against the +other Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages.

+ +

5. NO WARRANTY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS +AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, +WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely +responsible for determining the appropriateness of using and distributing the +Program and assumes all risks associated with its exercise of rights under this +Agreement , including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs or +equipment, and unavailability or interruption of operations.

+ +

6. DISCLAIMER OF LIABILITY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS +AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF +THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES.

+ +

7. GENERAL

+ +

If any provision of this Agreement is invalid +or unenforceable under applicable law, it shall not affect the validity or +enforceability of the remainder of the terms of this Agreement, and without +further action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable.

+ +

If Recipient institutes patent litigation +against any entity (including a cross-claim or counterclaim in a lawsuit) +alleging that the Program itself (excluding combinations of the Program with +other software or hardware) infringes such Recipient's patent(s), then such +Recipient's rights granted under Section 2(b) shall terminate as of the date +such litigation is filed.

+ +

All Recipient's rights under this Agreement +shall terminate if it fails to comply with any of the material terms or +conditions of this Agreement and does not cure such failure in a reasonable +period of time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use and +distribution of the Program as soon as reasonably practicable. However, +Recipient's obligations under this Agreement and any licenses granted by +Recipient relating to the Program shall continue and survive.

+ +

Everyone is permitted to copy and distribute +copies of this Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The Agreement +Steward reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement Steward has +the right to modify this Agreement. The Eclipse Foundation is the initial +Agreement Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each new version +of the Agreement will be given a distinguishing version number. The Program +(including Contributions) may always be distributed subject to the version of +the Agreement under which it was received. In addition, after a new version of +the Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly stated +in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to +the intellectual property of any Contributor under this Agreement, whether +expressly, by implication, estoppel or otherwise. All rights in the Program not +expressly granted under this Agreement are reserved.

+ +

This Agreement is governed by the laws of the +State of New York and the intellectual property laws of the United States of +America. No party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each party waives +its rights to a jury trial in any resulting litigation.

+ +

 

+ +
+ + + + \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties new file mode 100644 index 00000000000..76773117609 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties @@ -0,0 +1,168 @@ +############################################################################### +# Copyright (c) 2012 Anton Gorenkov and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - initial API and implementation +# Marc-Andre Laperle +############################################################################### +# features.properties +# contains externalized strings for feature.xml +# "%foo" in feature.xml corresponds to the key "foo" in this file +# java.io.Properties file (ISO 8859-1 with "\" escapes) +# This file should be translated. + +# "featureName" property - name of the feature +featureName=C/C++ Unit Testing Support + +# "providerName" property - name of the company that provides the feature +providerName=Eclipse CDT + +# "updateSiteName" property - label for the update site +updateSiteName=Eclipse CDT Update Site + +# "description" property - description of the feature +description=Support for running unit tests + +# copyright +copyright=\ +Copyright (c) 2012 Anton Gorenkov and others.\n\ +All rights reserved. This program and the accompanying materials\n\ +are made available under the terms of the Eclipse Public License v1.0\n\ +which accompanies this distribution, and is available at\n\ +http://www.eclipse.org/legal/epl-v10.html + +# "licenseURL" property - URL of the "Feature License" +# do not translate value - just change to point to a locale-specific HTML page +licenseURL=license.html + +# "license" property - text of the "Feature Update License" +# should be plain text version of license agreement pointed to be "licenseURL" +license=\ +Eclipse Foundation Software User Agreement\n\ +February 1, 2011\n\ +\n\ +Usage Of Content\n\ +\n\ +THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\ +OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\ +USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\ +AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\ +NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\ +AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\ +AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\ +OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\ +TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\ +OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\ +BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\ +\n\ +Applicable Licenses\n\ +\n\ +Unless otherwise indicated, all Content made available by the\n\ +Eclipse Foundation is provided to you under the terms and conditions of\n\ +the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\ +provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\ +For purposes of the EPL, "Program" will mean the Content.\n\ +\n\ +Content includes, but is not limited to, source code, object code,\n\ +documentation and other files maintained in the Eclipse Foundation source code\n\ +repository ("Repository") in software modules ("Modules") and made available\n\ +as downloadable archives ("Downloads").\n\ +\n\ + - Content may be structured and packaged into modules to facilitate delivering,\n\ + extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\ + plug-in fragments ("Fragments"), and features ("Features").\n\ + - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\ + in a directory named "plugins".\n\ + - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\ + Each Feature may be packaged as a sub-directory in a directory named "features".\n\ + Within a Feature, files named "feature.xml" may contain a list of the names and version\n\ + numbers of the Plug-ins and/or Fragments associated with that Feature.\n\ + - Features may also include other Features ("Included Features"). Within a Feature, files\n\ + named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\ +\n\ +The terms and conditions governing Plug-ins and Fragments should be\n\ +contained in files named "about.html" ("Abouts"). The terms and\n\ +conditions governing Features and Included Features should be contained\n\ +in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\ +Licenses may be located in any directory of a Download or Module\n\ +including, but not limited to the following locations:\n\ +\n\ + - The top-level (root) directory\n\ + - Plug-in and Fragment directories\n\ + - Inside Plug-ins and Fragments packaged as JARs\n\ + - Sub-directories of the directory named "src" of certain Plug-ins\n\ + - Feature directories\n\ +\n\ +Note: if a Feature made available by the Eclipse Foundation is installed using the\n\ +Provisioning Technology (as defined below), you must agree to a license ("Feature \n\ +Update License") during the installation process. If the Feature contains\n\ +Included Features, the Feature Update License should either provide you\n\ +with the terms and conditions governing the Included Features or inform\n\ +you where you can locate them. Feature Update Licenses may be found in\n\ +the "license" property of files named "feature.properties" found within a Feature.\n\ +Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\ +terms and conditions (or references to such terms and conditions) that\n\ +govern your use of the associated Content in that directory.\n\ +\n\ +THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\ +TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\ +SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ +\n\ + - Eclipse Distribution License Version 1.0 (available at http://www.eclipse.org/licenses/edl-v1.0.html)\n\ + - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ + - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ + - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ + - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ + - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ +\n\ +IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ +TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\ +is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\ +govern that particular Content.\n\ +\n\ +\n\Use of Provisioning Technology\n\ +\n\ +The Eclipse Foundation makes available provisioning software, examples of which include,\n\ +but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\ +the purpose of allowing users to install software, documentation, information and/or\n\ +other materials (collectively "Installable Software"). This capability is provided with\n\ +the intent of allowing such users to install, extend and update Eclipse-based products.\n\ +Information about packaging Installable Software is available at\n\ +http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\ +\n\ +You may use Provisioning Technology to allow other parties to install Installable Software.\n\ +You shall be responsible for enabling the applicable license agreements relating to the\n\ +Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\ +in accordance with the Specification. By using Provisioning Technology in such a manner and\n\ +making it available in accordance with the Specification, you further acknowledge your\n\ +agreement to, and the acquisition of all necessary rights to permit the following:\n\ +\n\ + 1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\ + the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\ + extending or updating the functionality of an Eclipse-based product.\n\ + 2. During the Provisioning Process, the Provisioning Technology may cause third party\n\ + Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\ + 3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\ + govern the use of the Installable Software ("Installable Software Agreement") and such\n\ + Installable Software Agreement shall be accessed from the Target Machine in accordance\n\ + with the Specification. Such Installable Software Agreement must inform the user of the\n\ + terms and conditions that govern the Installable Software and must solicit acceptance by\n\ + the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\ + indication of agreement by the user, the provisioning Technology will complete installation\n\ + of the Installable Software.\n\ +\n\ +Cryptography\n\ +\n\ +Content may contain encryption software. The country in which you are\n\ +currently may have restrictions on the import, possession, and use,\n\ +and/or re-export to another country, of encryption software. BEFORE\n\ +using any encryption software, please check the country's laws,\n\ +regulations and policies concerning the import, possession, or use, and\n\ +re-export of encryption software, to see if this is permitted.\n\ +\n\ +Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n +########### end of license property ########################################## diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml new file mode 100644 index 00000000000..2c9b6cee4e1 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml @@ -0,0 +1,52 @@ + + + + + %description + + + + %copyright + + + + %license + + + + + + + + + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/license.html b/testsrunner/org.eclipse.cdt.testsrunner.feature/license.html new file mode 100644 index 00000000000..f19c483b9c8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/license.html @@ -0,0 +1,108 @@ + + + + + +Eclipse Foundation Software User Agreement + + + +

Eclipse Foundation Software User Agreement

+

February 1, 2011

+ +

Usage Of Content

+ +

THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE + OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR + NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND + CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.

+ +

Applicable Licenses

+ +

Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 + ("EPL"). A copy of the EPL is provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html. + For purposes of the EPL, "Program" will mean the Content.

+ +

Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").

+ +
    +
  • Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").
  • +
  • Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".
  • +
  • A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + and/or Fragments associated with that Feature.
  • +
  • Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.
  • +
+ +

The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +including, but not limited to the following locations:

+ +
    +
  • The top-level (root) directory
  • +
  • Plug-in and Fragment directories
  • +
  • Inside Plug-ins and Fragments packaged as JARs
  • +
  • Sub-directories of the directory named "src" of certain Plug-ins
  • +
  • Feature directories
  • +
+ +

Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in +that directory.

+ +

THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE +OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):

+ + + +

IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please +contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.

+ + +

Use of Provisioning Technology

+ +

The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at http://eclipse.org/equinox/p2/repository_packaging.html + ("Specification").

+ +

You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the + applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology + in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the + Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:

+ +
    +
  1. A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + product.
  2. +
  3. During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be + accessed and copied to the Target Machine.
  4. +
  5. Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern + the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such + indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.
  6. +
+ +

Cryptography

+ +

Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to + another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import, + possession, or use, and re-export of encryption software, to see if this is permitted.

+ +

Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.

+ + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml new file mode 100644 index 00000000000..dfbd02d0f2b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 8.1.0-SNAPSHOT + ../../pom.xml + + + org.eclipse.cdt.features + 7.0.0-SNAPSHOT + org.eclipse.cdt.testsrunner.feature + eclipse-feature + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath new file mode 100644 index 00000000000..deb673668e9 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project new file mode 100644 index 00000000000..174ece0c727 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project @@ -0,0 +1,34 @@ + + + org.eclipse.cdt.testsrunner.gtest + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0e860bfc279 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,82 @@ +#Mon Apr 16 13:01:24 EEST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..6138224787a --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.cdt.testsrunner.gtest;singleton:=true +Bundle-Version: 7.0.0.qualifier +Bundle-Activator: org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerPlugin +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.5.0", + org.eclipse.cdt.testsrunner;bundle-version="3.5.0" +Export-Package: org.eclipse.cdt.testsrunner.internal.gtest;x-friends:="org.eclipse.cdt.testsrunner.test" diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html b/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html new file mode 100644 index 00000000000..d7c511887d6 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html @@ -0,0 +1,24 @@ + + +About + + +

About This Content

+ +

June 22, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties new file mode 100644 index 00000000000..55d9be83320 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties @@ -0,0 +1,21 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### + +bin.includes = plugin.xml,\ + plugin.properties,\ + about.html,\ + .,\ + META-INF/ +javadoc.packages = org.eclipse.cdt.launch.ui.*,\ + org.eclipse.cdt.launch.sourcelookup*,\ + org.eclipse.cdt.launch.* +source.. = src/ +src.includes = about.html diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties new file mode 100644 index 00000000000..f96761da73b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +pluginName=C/C++ Development Tools Google Tests Runner Support +providerName=Eclipse CDT + +GoogleTestsRunner.name=Google Tests Runner +GoogleTestsRunner.description=Tests runner for a test module based on Google C++ Testing Framework diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml new file mode 100644 index 00000000000..152f28a03e2 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml new file mode 100644 index 00000000000..50dd36fb314 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 8.1.0-SNAPSHOT + ../../pom.xml + + + 7.0.0-SNAPSHOT + org.eclipse.cdt.testsrunner.gtest + eclipse-plugin + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java new file mode 100644 index 00000000000..6aa1056514d --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.gtest; + +import org.eclipse.osgi.util.NLS; + +public class GoogleTestsRunnerMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerMessages"; //$NON-NLS-1$ + public static String GoogleTestsRunner_error_format; + public static String GoogleTestsRunner_io_error_prefix; + public static String OutputHandler_getparam_message; + public static String OutputHandler_unexpected_case_end; + public static String OutputHandler_unexpected_output; + public static String OutputHandler_unexpected_suite_end; + public static String OutputHandler_unknown_error_prefix; + public static String OutputHandler_unknown_location_format; + public static String OutputHandler_unknown_test_status; + public static String OutputHandler_wrong_groups_count; + public static String OutputHandler_wrong_suite_name; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, GoogleTestsRunnerMessages.class); + } + + private GoogleTestsRunnerMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties new file mode 100644 index 00000000000..e329ed2d6e0 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties @@ -0,0 +1,21 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +GoogleTestsRunner_error_format={0}: {1} +GoogleTestsRunner_io_error_prefix=I/O Error: +OutputHandler_getparam_message=Instantiated with GetParam() = {0} +OutputHandler_unexpected_case_end=End of test case "{0}" is not expected, because the last started case is "{1}". +OutputHandler_unexpected_output=Unexpected test module output. +OutputHandler_unexpected_suite_end=End of test suite "{0}" is not expected, because the last started suite is "{1}". +OutputHandler_unknown_error_prefix=Unknown error during parsing Google Test module output: +OutputHandler_unknown_location_format=Unknown location format. +OutputHandler_unknown_test_status=Test status value "{0}" is unknown. +OutputHandler_wrong_groups_count=State with pattern "{0}" should has {1} groups but has {2}. +OutputHandler_wrong_suite_name=A test case "{0}" belongs to test suite "{1}", but the last started suite is "{2}". diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java new file mode 100644 index 00000000000..1ddb7430e81 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.gtest; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; + + +/** + * The activator class controls the plug-in life cycle + */ +public class GoogleTestsRunnerPlugin extends Plugin { + + /** The plug-in ID .*/ + public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.gtest"; //$NON-NLS-1$ + + /** Plug-in instance. */ + private static GoogleTestsRunnerPlugin plugin; + + + public GoogleTestsRunnerPlugin() { + super(); + plugin = this; + } + + /** + * Returns the Boost Tests Runner provider plug-in instance. + * + * @return the plug-in instance + */ + public static GoogleTestsRunnerPlugin getDefault() { + return plugin; + } + + /** Convenience method which returns the unique identifier of this plugin. */ + public static String getUniqueIdentifier() { + return PLUGIN_ID; + } + + /** + * Logs the specified status with this plug-in's log. + * + * @param status status to log + */ + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + + /** + * Logs an internal error with the specified throwable + * + * @param e the exception to be logged + */ + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e)); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java new file mode 100644 index 00000000000..17ca3bd321e --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.gtest; + +import java.io.IOException; +import java.io.InputStream; +import java.text.MessageFormat; + +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.TestingException; + + +/** + * The Tests Runner provider plug-in to run tests with Google Testing framework. + * + * Parses the text test module to output and provides the data for the Tests + * Runner Plug-In. + */ +public class GoogleTestsRunnerProvider implements ITestsRunnerProvider { + + private static final String TEST_PATHS_DELIMITED = ":"; //$NON-NLS-1$ + private static final String TEST_PATH_PARTS_DELIMITED = "."; //$NON-NLS-1$ + private static final String ALL_TESTS= ".*"; //$NON-NLS-1$ + + + @Override + public String[] getAdditionalLaunchParameters(String[][] testPaths) { + final String[] gtestParameters = { + "--gtest_repeat=1", //$NON-NLS-1$ + "--gtest_print_time=1", //$NON-NLS-1$ + "--gtest_color=no", //$NON-NLS-1$ + }; + String[] result = gtestParameters; + + // Build tests filter + if (testPaths != null && testPaths.length >= 1) { + StringBuilder sb = new StringBuilder("--gtest_filter="); //$NON-NLS-1$ + boolean needTestPathDelimiter = false; + for (String[] testPath : testPaths) { + if (needTestPathDelimiter) { + sb.append(TEST_PATHS_DELIMITED); + } else { + needTestPathDelimiter = true; + } + boolean needTestPathPartDelimiter = false; + for (String testPathPart : testPath) { + if (needTestPathPartDelimiter) { + sb.append(TEST_PATH_PARTS_DELIMITED); + } else { + needTestPathPartDelimiter = true; + } + sb.append(testPathPart); + } + // If it is a test suite + if (testPath.length <= 1) { + sb.append(ALL_TESTS); + } + } + result = new String[gtestParameters.length + 1]; + System.arraycopy(gtestParameters, 0, result, 0, gtestParameters.length); + result[gtestParameters.length] = sb.toString(); + } + return result; + } + + /** + * Construct the error message from prefix and detailed description. + * + * @param prefix prefix + * @param description detailed description + * @return the full message + */ + private String getErrorText(String prefix, String description) { + return MessageFormat.format(GoogleTestsRunnerMessages.GoogleTestsRunner_error_format, prefix, description); + } + + @Override + public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException { + + try { + OutputHandler ouputHandler = new OutputHandler(modelUpdater); + ouputHandler.run(inputStream); + } catch (IOException e) { + throw new TestingException(getErrorText(GoogleTestsRunnerMessages.GoogleTestsRunner_io_error_prefix, e.getLocalizedMessage())); + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java new file mode 100644 index 00000000000..3a58563d5be --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java @@ -0,0 +1,645 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.gtest; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.eclipse.cdt.testsrunner.model.TestingException; +import org.xml.sax.SAXException; + + +/** + *

+ * Parses the output of Google Testing Framework and notifies the Tests Runner + * Core about how the testing process is going. + *

+ *

+ * Unfortunately, gtest does not provide a realtime XML output (yes, it has XML + * output, but it is generated after testing process is done), so we have to + * parse its output that is less reliable. + *

+ *

+ * The parsing is done with a simple FSM (Final State Machine). There is an + * internal state that changes when input tokens (gtest output lines) come. + * There is a transitions table that is used to determine what is the next state + * depending on the current one and the input token. The state may define + * onEnter and onExit actions to do the useful job. + *

+ */ +public class OutputHandler { + + /** + * Base class for the FSM internal state. + */ + class State { + + /** Stores the regular expression by which the state should be entered. */ + private Pattern enterPattern; + + /** The regular expression matcher. */ + private Matcher matcher; + + /** Groups count in a regular expression. */ + private int groupCount; + + /** + * The constructor. + * + * @param enterRegex the regular expression by which the state should be + * entered + */ + State(String enterRegex) { + this(enterRegex, -1); + } + + /** + * The constructor. + * + * @param enterRegex the regular expression by which the state should be + * entered + * @param groupCount groups count in a regular expression. It is used + * just to make debug easier and the parser more reliable. + */ + State(String enterRegex, int groupCount) { + enterPattern = Pattern.compile(enterRegex); + this.groupCount = groupCount; + } + + /** + * Checks whether the specified string matches the enter pattern + * (regular expression). If it is so the state should be entered. + * + * @param line input line (token) + * @return true if matches and false otherwise + * @throws TestingException if groups count does not match the defined + * in constructor number. + */ + public boolean match(String line) throws TestingException { + matcher = enterPattern.matcher(line); + boolean groupsCountOk = groupCount == -1 || matcher.groupCount() == groupCount; + if (!groupsCountOk) { + generateInternalError( + MessageFormat.format( + GoogleTestsRunnerMessages.OutputHandler_wrong_groups_count, + enterPattern.pattern(), matcher.groupCount(), groupCount + ) + ); + } + boolean matches = matcher.matches(); + if (!matches || !groupsCountOk) { + // Do not keep the reference - it will be unnecessary anyway + matcher = null; + } + return matches; + } + + /** + * Returns the matched group value by index. + * + * @param groupNumber group index + * @return group value + */ + protected String group(int groupNumber) { + return matcher.group(groupNumber); + } + + /** + * Action that triggers on state enter. + * + * @param previousState previous state + * @throws TestingException if testing error is detected + */ + public void onEnter(State previousState) throws TestingException {} + + /** + * Action that triggers on state exit. + * + * @param previousState next state + * @throws TestingException if testing error is detected + */ + public void onExit(State nextState) {} + + /** + * Common routine that constructs full test suite name by name and type + * parameter. + * + * @param name test suite name + * @param typeParameter type parameter + * @return full test suite name + */ + protected String getTestSuiteName(String name, String typeParameter) { + return (typeParameter != null) ? MessageFormat.format("{0}({1})", name, typeParameter.trim()) : name; //$NON-NLS-1$ + } + } + + + /** + * The state is activated when a new test suite is started. + */ + class TestSuiteStart extends State { + + /** Stores the matched type parameter. */ + private String typeParameter; + + TestSuiteStart(String enterRegex, int groupCount) { + super(enterRegex, groupCount); + } + + /** + * Stores type parameter and notify Tests Runner Core about test suite + * start. + */ + @Override + public void onEnter(State previousState) { + typeParameter = group(3); + modelUpdater.enterTestSuite(getTestSuiteName(group(1), typeParameter)); + } + + /** + * Provides access to the matched type parameter. + * + * @return type parameter value + */ + public String getTypeParameter() { + return typeParameter; + } + } + + + /** + * The state is activated when a new test case is started. + */ + class TestCaseStart extends State { + + TestCaseStart(String enterRegex, int groupCount) { + super(enterRegex, groupCount); + } + + /** + * Extract current test case and test suite names and notify Tests + * Runner Core about test case start. + * + * @throws TestingException if extracted test suite name does not match + * last entered test suite name. + */ + @Override + public void onEnter(State previousState) throws TestingException { + String testCaseName = group(2); + String lastTestSuiteName = modelUpdater.currentTestSuite().getName(); + String currTestSuiteName = getTestSuiteName(group(1), stateTestSuiteStart.getTypeParameter()); + if (!lastTestSuiteName.equals(currTestSuiteName)) { + generateInternalError( + MessageFormat.format( + GoogleTestsRunnerMessages.OutputHandler_wrong_suite_name, + testCaseName, currTestSuiteName, lastTestSuiteName + ) + ); + } + modelUpdater.enterTestCase(testCaseName); + } + } + + + /** + * The state is activated when an error message's location is started. + */ + class ErrorMessageLocation extends State { + + /** Stores the message location file name. */ + private String messageFileName; + + /** Stores the message location line number. */ + private int messageLineNumber; + + /** Stores the first part of the message. */ + private String messagePart; + + ErrorMessageLocation(String enterRegex, int groupCount) { + super(enterRegex, groupCount); + } + + /** + * Extract the data for the message location (file name, line number). + * The data may be provided in a common style ("/path/file:line" with + * the message text starting on the next line) or Visual Studio style + * ("/path/file(line):" with the message text continuing on the same + * line). It is also possible not to specify line number at all + * ("/path/file:"). + * + * @throws TestingException if location format cannot be recognized. + */ + @Override + public void onEnter(State previousState) throws TestingException { + String fileNameIfLinePresent = group(2); + String fileNameIfLineAbsent = group(6); + String lineNumberCommon = group(4); + String lineNumberVS = group(5); + if (fileNameIfLinePresent != null) { + if (lineNumberCommon != null) { + messageFileName = fileNameIfLinePresent; + messageLineNumber = Integer.parseInt(lineNumberCommon.trim()); + } else if (lineNumberVS != null) { + messageFileName = fileNameIfLinePresent; + messageLineNumber = Integer.parseInt(lineNumberVS.trim()); + } else { + if (!modelUpdater.currentTestSuite().getName().equals(group(1))) { + generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unknown_location_format); + } + } + } else if (fileNameIfLineAbsent != null) { + if (lineNumberCommon == null && lineNumberVS == null) { + messageFileName = fileNameIfLineAbsent; + messageLineNumber = DEFAULT_LOCATION_LINE; + } else { + generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unknown_location_format); + } + } + // Check special case when file is not known - reset location + if (messageFileName.equals("unknown file")) { //$NON-NLS-1$ + messageFileName = DEFAULT_LOCATION_FILE; + } + // NOTE: For Visual Studio style there is also first part of the message at this line + messagePart = group(8); + } + + /** + * Provides access to the message location file name. + * + * @return file name + */ + public String getMessageFileName() { + return messageFileName; + } + + /** + * Provides access to the message location line number. + * + * @return line number + */ + public int getMessageLineNumber() { + return messageLineNumber; + } + + /** + * Provides access to the first part of the message. + * + * @return message part + */ + public String getMessagePart() { + return messagePart; + } + } + + + /** + * The state is activated when an error message text is started or continued. + */ + class ErrorMessage extends State { + + /** Stores the error message text that was already read. */ + private StringBuilder messagePart = new StringBuilder(); + + ErrorMessage(String enterRegex, int groupCount) { + super(enterRegex, groupCount); + } + + /** + * Collects the error message parts into internal buffer. If the + * previous state is not the same (it should be + * stateErrorMessageLocation) - get the message part from it. + */ + @Override + public void onEnter(State previousState) { + boolean needEndOfLine = (this == previousState); + if (this != previousState) { + String firstMessagePart = stateErrorMessageLocation.getMessagePart(); + if (firstMessagePart != null) { + messagePart.append(firstMessagePart); + needEndOfLine = true; + } + } + if (needEndOfLine) { + messagePart.append(System.getProperty("line.separator")); //$NON-NLS-1$ + } + messagePart.append(group(1)); + } + + /** + * Notifies the Tests Runner Core about new test message. + */ + @Override + public void onExit(State nextState) { + if (this != nextState) { + modelUpdater.addTestMessage( + stateErrorMessageLocation.getMessageFileName(), + stateErrorMessageLocation.getMessageLineNumber(), + ITestMessage.Level.Error, + messagePart.toString() + ); + messagePart.setLength(0); + } + } + } + + + /** + * The state is activated when a test trace is started or continued. + */ + class TestTrace extends ErrorMessageLocation { + + TestTrace(String enterRegex, int groupCount) { + super(enterRegex, groupCount); + } + + /** + * Notifies the Tests Runner Core about new test message with test trace + * info. + */ + @Override + public void onEnter(State previousState) throws TestingException { + super.onEnter(previousState); + modelUpdater.addTestMessage( + getMessageFileName(), + getMessageLineNumber(), + ITestMessage.Level.Info, + getMessagePart() + ); + } + } + + + /** + * The state is activated when a test case is finished. + */ + class TestCaseEnd extends State { + + TestCaseEnd(String enterRegex, int groupCount) { + super(enterRegex, groupCount); + } + + /** + * Sets the test case execution time, status and notify Tests Runner + * Core about test case end. + * + * @throws TestingException if current test suite or case name does not + * match last entered test suite or case name or if test status is not + * known. + */ + @Override + public void onEnter(State previousState) throws TestingException { + String lastTestSuiteName = modelUpdater.currentTestSuite().getName(); + String explicitTypeParameter = group(5); + String typeParameter = explicitTypeParameter != null ? explicitTypeParameter : stateTestSuiteStart.getTypeParameter(); + String currTestSuiteName = getTestSuiteName(group(2), typeParameter); + if (!lastTestSuiteName.equals(currTestSuiteName)) { + generateInternalError( + MessageFormat.format( + GoogleTestsRunnerMessages.OutputHandler_wrong_suite_name, + group(2), currTestSuiteName, lastTestSuiteName + ) + ); + } + String lastTestCaseName = modelUpdater.currentTestCase().getName(); + if (!lastTestCaseName.equals(group(3))) { + generateInternalError( + MessageFormat.format( + GoogleTestsRunnerMessages.OutputHandler_unexpected_case_end, + group(3), lastTestCaseName + ) + ); + } + String testStatusStr = group(1); + ITestItem.Status testStatus = ITestItem.Status.Skipped; + if (testStatusStr.equals(testStatusOk)) { + testStatus = ITestItem.Status.Passed; + } else if (testStatusStr.equals(testStatusFailed)) { + testStatus = ITestItem.Status.Failed; + } else { + generateInternalError(MessageFormat.format(GoogleTestsRunnerMessages.OutputHandler_unknown_test_status, testStatusStr)); + } + String getParamValue = group(7); + if (getParamValue != null) { + modelUpdater.addTestMessage( + DEFAULT_LOCATION_FILE, + DEFAULT_LOCATION_LINE, + ITestMessage.Level.Info, + MessageFormat.format(GoogleTestsRunnerMessages.OutputHandler_getparam_message, getParamValue) + ); + + } + modelUpdater.setTestingTime(Integer.parseInt(group(8))); + modelUpdater.setTestStatus(testStatus); + modelUpdater.exitTestCase(); + } + } + + + /** + * The state is activated when a test suite is finished. + */ + class TestSuiteEnd extends State { + + TestSuiteEnd(String enterRegex, int groupCount) { + super(enterRegex, groupCount); + } + + /** + * Notify Tests Runner Core about test suite end. + * + * @throws TestingException if current test suite name does not match + * last entered test suite name. + */ + @Override + public void onEnter(State previousState) throws TestingException { + String lastTestSuiteName = modelUpdater.currentTestSuite().getName(); + String currTestSuiteName = getTestSuiteName(group(1), stateTestSuiteStart.getTypeParameter()); + if (!lastTestSuiteName.equals(currTestSuiteName)) { + generateInternalError( + MessageFormat.format( + GoogleTestsRunnerMessages.OutputHandler_unexpected_suite_end, + currTestSuiteName, lastTestSuiteName + ) + ); + } + modelUpdater.exitTestSuite(); + } + } + + + /** The default file name for test message location. */ + private static final String DEFAULT_LOCATION_FILE = null; + + /** The default line number for test message location. */ + private static final int DEFAULT_LOCATION_LINE = 1; + + // Common regular expression parts + static private String regexTestSuiteName = "([^,]+)"; //$NON-NLS-1$ + static private String regexParameterInstantiation = "(\\s*,\\s+where\\s+TypeParam\\s*=([^,(]+))?"; //$NON-NLS-1$ + static private String regexTestName = regexTestSuiteName+"\\.([^,]+)"; //$NON-NLS-1$ + static private String regexTestCount = "\\d+\\s+tests?"; //$NON-NLS-1$ + static private String regexTestTime = "(\\d+)\\s+ms"; //$NON-NLS-1$ + /* Matches location in the following formats: + * - /file:line: + * - /file(line): + * - /file: (with no line number specified) + * Groups: + * 1 - all except ":" + * 2 - file name (if line present) * + * 3 - line number with delimiters + * 4 - line number (common style) * + * 5 - line number (Visual Studio style) * + * 6 - file name (if no line number specified) * + * Using: + * - group 2 with 4 or 5 (if line number was specified) + * - group 6 (if filename only was specified) + */ + static private String regexLocation = "((.*)(:(\\d+)|\\((\\d+)\\))|(.*[^):])):"; //$NON-NLS-1$ + + // Test statuses representation + static private String testStatusOk = "OK"; //$NON-NLS-1$ + static private String testStatusFailed = "FAILED"; //$NON-NLS-1$ + + + // All available states in FSM + private State stateInitial = new State(""); //$NON-NLS-1$ + private State stateInitialized = new State(".*Global test environment set-up.*"); //$NON-NLS-1$ + private TestSuiteStart stateTestSuiteStart = new TestSuiteStart("\\[-*\\]\\s+"+regexTestCount+"\\s+from\\s+"+regexTestSuiteName+regexParameterInstantiation, 3); //$NON-NLS-1$ //$NON-NLS-2$ + private State stateTestCaseStart = new TestCaseStart("\\[\\s*RUN\\s*\\]\\s+"+regexTestName, 2); //$NON-NLS-1$ + private ErrorMessageLocation stateErrorMessageLocation = new ErrorMessageLocation(regexLocation+"\\s+(Failure|error: (.*))", 8); //$NON-NLS-1$ + private State stateErrorMessage = new ErrorMessage("(.*)", 1); //$NON-NLS-1$ + private State stateTestTraceStart = new State(".*Google Test trace.*"); //$NON-NLS-1$ + // NOTE: Use 8 groups instead of 7 cause we need to be consistent with ErrorMessageLocation (as we subclass it) + private State stateTestTrace = new TestTrace(regexLocation+"\\s+((.*))", 8); //$NON-NLS-1$ + private State stateTestCaseEnd = new TestCaseEnd("\\[\\s*("+testStatusOk+"|"+testStatusFailed+")\\s*\\]\\s+"+regexTestName+regexParameterInstantiation+"(\\s*,\\s+where\\s+GetParam\\s*\\(\\s*\\)\\s*=\\s*(.+))?\\s+\\("+regexTestTime+"\\)", 8); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + private State stateTestSuiteEnd = new TestSuiteEnd("\\[-*\\]\\s+"+regexTestCount+"\\s+from\\s+"+regexTestSuiteName+"\\s+\\("+regexTestTime+"\\s+total\\)", 2); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private State stateFinal = new State(".*Global test environment tear-down.*"); //$NON-NLS-1$ + // NOTE: This state is a special workaround for empty test modules (they haven't got global test environment set-up/tear-down). They should be always passed. + private State stateEmptyTestModuleFinal = new State(".*\\[\\s*PASSED\\s*\\]\\s+0\\s+tests.*"); //$NON-NLS-1$ + + // Transitions table + private Map transitions = new HashMap(); + { + // NOTE: Next states order is important! + transitions.put( from(stateInitial), to(stateInitialized, stateEmptyTestModuleFinal) ); + transitions.put( from(stateInitialized), to(stateTestSuiteStart) ); + transitions.put( from(stateTestSuiteStart), to(stateTestCaseStart) ); + transitions.put( from(stateTestCaseStart), to(stateTestCaseEnd, stateErrorMessageLocation) ); + transitions.put( from(stateErrorMessageLocation), to(stateTestTraceStart, stateTestCaseEnd, stateErrorMessageLocation, stateErrorMessage) ); + transitions.put( from(stateErrorMessage), to(stateTestTraceStart, stateTestCaseEnd, stateErrorMessageLocation, stateErrorMessage) ); + transitions.put( from(stateTestTraceStart), to(stateTestTrace) ); + transitions.put( from(stateTestTrace), to(stateTestCaseEnd, stateErrorMessageLocation, stateTestTrace) ); + transitions.put( from(stateTestCaseEnd), to(stateTestCaseStart, stateTestSuiteEnd) ); + transitions.put( from(stateTestSuiteEnd), to(stateTestSuiteStart, stateFinal) ); + } + + /** Current FSM state. */ + private State currentState; + + /** The interface to notify the Tests Runner Core */ + private ITestModelUpdater modelUpdater; + + + OutputHandler(ITestModelUpdater modelUpdater) { + this.modelUpdater = modelUpdater; + } + + /** + * Runs the parsing process. Initializes the FSM, selects new states with + * transitions table and checks whether the parsing completes successfully. + * + * @param inputStream gtest test module output stream + * @throws IOException if stream reading error happens + * @throws TestingException if testing error happens + */ + public void run(InputStream inputStream) throws IOException, TestingException { + // Initialize input stream reader + InputStreamReader streamReader = new InputStreamReader(inputStream); + BufferedReader reader = new BufferedReader(streamReader); + String line; + boolean finalizedProperly = false; + + // Initialize internal state + currentState = stateInitial; + while ( ( line = reader.readLine() ) != null ) { + // Search for the next possible state + State[] possibleNextStates = transitions.get(currentState); + if (possibleNextStates == null) { + // Final state, stop running + finalizedProperly = true; + break; + } + for (State nextState : possibleNextStates) { + if (nextState.match(line)) { + // Next state found - send notifications to the states + currentState.onExit(nextState); + State previousState = currentState; + currentState = nextState; + nextState.onEnter(previousState); + break; + } + } + // NOTE: We cannot be sure that we cover all the output of gtest with our regular expressions + // (e.g. some framework notes or warnings may be uncovered etc.), so we just skip unmatched + // lines without an error + } + // Check whether the last line leads to the final state + if (transitions.get(currentState) == null) { + finalizedProperly = true; + } + if (!finalizedProperly) { + generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unexpected_output); + } + } + + /** + * Throws the testing exception with unknown internal error prefix and the specified description. + * + * @param additionalInfo additional description of what happens + * @throws SAXException the exception that will be thrown + */ + private void generateInternalError(String additionalInfo) throws TestingException { + TestingException e = new TestingException(GoogleTestsRunnerMessages.OutputHandler_unknown_error_prefix+additionalInfo); + GoogleTestsRunnerPlugin.log(e); + throw e; + } + + /** + * Helper functions to make code more readable. + * + * @param fromState state to return + * @return passed state + */ + private State from(State fromState) { + return fromState; + } + + /** + * Helper functions to make code more readable. + * + * @param toStates states array to return + * @return passed states array + */ + private State[] to(State... toStates) { + return toStates; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath new file mode 100644 index 00000000000..deb673668e9 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/.project b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.project new file mode 100644 index 00000000000..0a08b2e75bc --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.project @@ -0,0 +1,34 @@ + + + org.eclipse.cdt.testsrunner.qttest + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0e860bfc279 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,82 @@ +#Mon Apr 16 13:01:24 EEST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..c78021d971b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.cdt.testsrunner.qttest;singleton:=true +Bundle-Version: 7.0.0.qualifier +Bundle-Activator: org.eclipse.cdt.testsrunner.internal.qttest.QtTestsRunnerPlugin +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.5.0", + org.eclipse.cdt.testsrunner;bundle-version="3.5.0" +Export-Package: org.eclipse.cdt.testsrunner.internal.qttest;x-friends:="org.eclipse.cdt.testsrunner.test" diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html b/testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html new file mode 100644 index 00000000000..d7c511887d6 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html @@ -0,0 +1,24 @@ + + +About + + +

About This Content

+ +

June 22, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties new file mode 100644 index 00000000000..55d9be83320 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties @@ -0,0 +1,21 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### + +bin.includes = plugin.xml,\ + plugin.properties,\ + about.html,\ + .,\ + META-INF/ +javadoc.packages = org.eclipse.cdt.launch.ui.*,\ + org.eclipse.cdt.launch.sourcelookup*,\ + org.eclipse.cdt.launch.* +source.. = src/ +src.includes = about.html diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties new file mode 100644 index 00000000000..1b0e34c4a70 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +pluginName=C/C++ Development Tools Qt Tests Runner Support +providerName=Eclipse CDT + +QtTestsRunner.name=Qt Tests Runner +QtTestsRunner.description=Tests runner for a test module based on Qt4 Testing framework diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml new file mode 100644 index 00000000000..54ac1fe1efb --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml new file mode 100644 index 00000000000..440914fe37b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 8.1.0-SNAPSHOT + ../../pom.xml + + + 7.0.0-SNAPSHOT + org.eclipse.cdt.testsrunner.qttest + eclipse-plugin + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java new file mode 100644 index 00000000000..63576878f94 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.qttest; + +import org.eclipse.osgi.util.NLS; + +public class QtTestsRunnerMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.qttest.QtTestsRunnerMessages"; //$NON-NLS-1$ + public static String QtTestsRunner_error_format; + public static String QtTestsRunner_io_error_prefix; + public static String QtTestsRunner_no_test_cases_to_rerun; + public static String QtTestsRunner_xml_error_prefix; + public static String QtXmlLogHandler_benchmark_result_message; + public static String QtXmlLogHandler_datatag_format; + public static String QtXmlLogHandler_metrics_unit_events; + public static String QtXmlLogHandler_metrics_unit_instructions; + public static String QtXmlLogHandler_metrics_unit_msec; + public static String QtXmlLogHandler_metrics_unit_ticks; + public static String QtXmlLogHandler_unknown_benchmarck_metric; + public static String QtXmlLogHandler_unknown_message_level; + public static String QtXmlLogHandler_wrong_tag_name; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, QtTestsRunnerMessages.class); + } + + private QtTestsRunnerMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties new file mode 100644 index 00000000000..6a5196e72d8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +QtTestsRunner_error_format={0}: {1} +QtTestsRunner_io_error_prefix=I/O Error: +QtTestsRunner_no_test_cases_to_rerun=There is no test cases to rerun (initialization and finalization test cases are not taken into account) +QtTestsRunner_xml_error_prefix=XML parse error: +QtXmlLogHandler_benchmark_result_message={0,number,\#.\#\#\#\#} {1} per iteration (total: {2}, iterations: {3}) +QtXmlLogHandler_datatag_format=({0}) +QtXmlLogHandler_metrics_unit_events=events +QtXmlLogHandler_metrics_unit_instructions=instr. +QtXmlLogHandler_metrics_unit_msec=msec +QtXmlLogHandler_metrics_unit_ticks=ticks +QtXmlLogHandler_unknown_benchmarck_metric=Benchmarck metric value "{0}" is not supported\! +QtXmlLogHandler_unknown_message_level=String "{0}" cannot be converted to a message level\! +QtXmlLogHandler_wrong_tag_name=Invalid XML format: Element "{0}" is not accepted\! diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java new file mode 100644 index 00000000000..705b631e78f --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.qttest; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; + + +/** + * The activator class controls the plug-in life cycle + */ +public class QtTestsRunnerPlugin extends Plugin { + + /** The plug-in ID .*/ + public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.qttest"; //$NON-NLS-1$ + + /** Plug-in instance. */ + private static QtTestsRunnerPlugin plugin; + + public QtTestsRunnerPlugin() { + super(); + plugin = this; + } + + /** + * Returns the Qt Tests Runner provider plug-in instance. + * + * @return the plug-in instance + */ + public static QtTestsRunnerPlugin getDefault() { + return plugin; + } + + /** Convenience method which returns the unique identifier of this plugin. */ + public static String getUniqueIdentifier() { + return PLUGIN_ID; + } + + /** + * Logs the specified status with this plug-in's log. + * + * @param status status to log + */ + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + + /** + * Logs an internal error with the specified throwable + * + * @param e the exception to be logged + */ + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e)); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java new file mode 100644 index 00000000000..7fb9fa8a579 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.qttest; + +import java.io.IOException; +import java.io.InputStream; +import java.text.MessageFormat; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.TestingException; +import org.xml.sax.SAXException; + +/** + * The Tests Runner provider plug-in to run tests with Qt Test library. + * + * Configures the test module to output in XML format, parses the output and + * provides the data for the Tests Runner Plug-in. + */ +public class QtTestsRunnerProvider implements ITestsRunnerProvider { + + /** + * Checks whether the specified path is "special" one ("initTestCase" or + * "cleanupTestCase"). + * + * @param testPath test path to check + * @return true if the path is special and false otherwise + */ + private boolean isSpecialTestPath(String[] testPath) { + // Root test suite should not be explicitly specified for rerun + if (testPath.length <= 1) { + return true; + } + // "initTestCase" & "cleanupTestCase" are special test case names and they should be skipped too + String testName = testPath[testPath.length-1]; + return testName.equals("initTestCase") || testName.equals("cleanupTestCase"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Returns the count of not "special" test paths. + * + * @param testPaths test paths array + * @return the count + * @see isSpecialTestPath() + */ + private int getNonSpecialTestsCount(String[][] testPaths) { + int result = 0; + for (int i = 0; i < testPaths.length; i++) { + String[] testPath = testPaths[i]; + result += isSpecialTestPath(testPath) ? 0 : 1; + } + return result; + } + + @Override + public String[] getAdditionalLaunchParameters(String[][] testPaths) throws TestingException { + final String[] qtParameters = { + "-xml", //$NON-NLS-1$ + "-flush", //$NON-NLS-1$ + }; + String[] result = qtParameters; + + if (testPaths != null) { + int testPathsLength = getNonSpecialTestsCount(testPaths); + // If there are only special test cases specified + if ((testPathsLength == 0) != (testPaths.length == 0)) { + throw new TestingException(QtTestsRunnerMessages.QtTestsRunner_no_test_cases_to_rerun); + } + + // Build tests filter + if (testPathsLength >= 1) { + result = new String[qtParameters.length + testPathsLength]; + System.arraycopy(qtParameters, 0, result, 0, qtParameters.length); + int resultIdx = qtParameters.length; + for (int i = 0; i < testPaths.length; i++) { + String[] testPath = testPaths[i]; + if (!isSpecialTestPath(testPath)) { + result[resultIdx] = testPath[testPath.length-1]; + resultIdx++; + } + } + } + } + return result; + } + + /** + * Construct the error message from prefix and detailed description. + * + * @param prefix prefix + * @param description detailed description + * @return the full message + */ + private String getErrorText(String prefix, String description) { + return MessageFormat.format(QtTestsRunnerMessages.QtTestsRunner_error_format, prefix, description); + } + + @Override + public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException { + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + SAXParser sp = spf.newSAXParser(); + sp.parse(inputStream, new QtXmlLogHandler(modelUpdater)); + + } catch (IOException e) { + throw new TestingException(getErrorText(QtTestsRunnerMessages.QtTestsRunner_io_error_prefix, e.getLocalizedMessage())); + + } catch (ParserConfigurationException e) { + throw new TestingException(getErrorText(QtTestsRunnerMessages.QtTestsRunner_xml_error_prefix, e.getLocalizedMessage())); + + } catch (SAXException e) { + throw new TestingException(getErrorText(QtTestsRunnerMessages.QtTestsRunner_xml_error_prefix, e.getLocalizedMessage())); + } + + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java new file mode 100644 index 00000000000..d1d17b7e895 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java @@ -0,0 +1,399 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.qttest; + +import java.text.MessageFormat; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestMessage.Level; +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.ITestCase; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + + +/** + * Parses the Qt Test XML log and notifies the Tests Runner Core about how the + * testing process is going. + * + * @note There is a terminology conflict between Qt Test library and Test + * Runner. Qt Test's "test case" is a "test suite" in Test Runner's terminology, + * Qt's "test function" is a "test case", the "incident" and "message" are + * "test messages". Be careful with it! + */ +public class QtXmlLogHandler extends DefaultHandler { + + // Qt Test XML log tags + private static final String XML_NODE_TEST_CASE = "TestCase"; //$NON-NLS-1$ + private static final String XML_NODE_TEST_FUNCTION = "TestFunction"; //$NON-NLS-1$ + private static final String XML_NODE_INCIDENT = "Incident"; //$NON-NLS-1$ + private static final String XML_NODE_MESSAGE = "Message"; //$NON-NLS-1$ + private static final String XML_NODE_DESCRIPTION = "Description"; //$NON-NLS-1$ + private static final String XML_NODE_ENVIRONMENT = "Environment"; //$NON-NLS-1$ + private static final String XML_NODE_QTVERSION = "QtVersion"; //$NON-NLS-1$ + private static final String XML_NODE_QTESTVERSION = "QTestVersion"; //$NON-NLS-1$ + private static final String XML_NODE_BENCHMARK = "BenchmarkResult"; //$NON-NLS-1$ + private static final String XML_NODE_DATATAG = "DataTag"; //$NON-NLS-1$ + + // Qt Test XML case statuses representation + private static final String XML_VALUE_INCIDENT_PASS = "pass"; //$NON-NLS-1$ + private static final String XML_VALUE_INCIDENT_XFAIL = "xfail"; //$NON-NLS-1$ + private static final String XML_VALUE_INCIDENT_FAIL = "fail"; //$NON-NLS-1$ + private static final String XML_VALUE_INCIDENT_XPASS = "xpass"; //$NON-NLS-1$ + private static final String XML_VALUE_INCIDENT_UNKNOWN = "??????"; //$NON-NLS-1$ + + // Qt Test XML log message levels representation + private static final String XML_VALUE_MESSAGE_WARN = "warn"; //$NON-NLS-1$ + private static final String XML_VALUE_MESSAGE_SYSTEM = "system"; //$NON-NLS-1$ + private static final String XML_VALUE_MESSAGE_QDEBUG = "qdebug"; //$NON-NLS-1$ + private static final String XML_VALUE_MESSAGE_QWARN = "qwarn"; //$NON-NLS-1$ + private static final String XML_VALUE_MESSAGE_QFATAL = "qfatal"; //$NON-NLS-1$ + private static final String XML_VALUE_MESSAGE_SKIP = "skip"; //$NON-NLS-1$ + private static final String XML_VALUE_MESSAGE_INFO = "info"; //$NON-NLS-1$ + private static final String XML_VALUE_MESSAGE_UNKNOWN = "??????"; //$NON-NLS-1$ + + // Qt Test XML log attributes + private static final String XML_ATTR_TEST_CASE_NAME = "name"; //$NON-NLS-1$ + private static final String XML_ATTR_TEST_FUNCTION_NAME = "name"; //$NON-NLS-1$ + private static final String XML_ATTR_TYPE = "type"; //$NON-NLS-1$ + private static final String XML_ATTR_FILE = "file"; //$NON-NLS-1$ + private static final String XML_ATTR_LINE = "line"; //$NON-NLS-1$ + private static final String XML_ATTR_BENCHMARK_METRIC = "metric"; //$NON-NLS-1$ + private static final String XML_ATTR_BENCHMARK_VALUE = "value"; //$NON-NLS-1$ + private static final String XML_ATTR_BENCHMARK_ITERATIONS = "iterations"; //$NON-NLS-1$ + private static final String XML_ATTR_DATA_TAG = "tag"; //$NON-NLS-1$ + + /** Maps the string message level representation to the Tests Runner internal enum code. */ + private static final Map STRING_TO_MESSAGE_LEVEL; + static { + Map aMap = new HashMap(); + aMap.put(XML_VALUE_MESSAGE_WARN, ITestMessage.Level.Warning); + aMap.put(XML_VALUE_MESSAGE_SYSTEM, ITestMessage.Level.Message); + aMap.put(XML_VALUE_MESSAGE_QDEBUG, ITestMessage.Level.Message); + aMap.put(XML_VALUE_MESSAGE_QWARN, ITestMessage.Level.Warning); + aMap.put(XML_VALUE_MESSAGE_QFATAL, ITestMessage.Level.FatalError); + aMap.put(XML_VALUE_MESSAGE_SKIP, ITestMessage.Level.Info); + aMap.put(XML_VALUE_MESSAGE_INFO, ITestMessage.Level.Info); + aMap.put(XML_VALUE_MESSAGE_UNKNOWN, ITestMessage.Level.FatalError); + // NOTE: Exception node is processed separately + STRING_TO_MESSAGE_LEVEL = Collections.unmodifiableMap(aMap); + } + + /** Maps the string incident status representation to the test case status. */ + private static final Map STRING_TO_TEST_STATUS; + static { + Map aMap = new HashMap(); + aMap.put(XML_VALUE_INCIDENT_PASS, ITestCase.Status.Passed); + aMap.put(XML_VALUE_INCIDENT_XFAIL, ITestCase.Status.Failed); + aMap.put(XML_VALUE_INCIDENT_FAIL, ITestCase.Status.Failed); + aMap.put(XML_VALUE_INCIDENT_XPASS, ITestCase.Status.Failed); + aMap.put(XML_VALUE_INCIDENT_UNKNOWN, ITestCase.Status.Aborted); + // NOTE: Exception node is processed separately + STRING_TO_TEST_STATUS = Collections.unmodifiableMap(aMap); + } + + /** Maps the string incident status representation to the test message level to log about it. */ + private static final Map STRING_INCIDENT_TO_MESSAGE_LEVEL; + static { + Map aMap = new HashMap(); + aMap.put(XML_VALUE_INCIDENT_PASS, ITestMessage.Level.Info); + aMap.put(XML_VALUE_INCIDENT_XFAIL, ITestMessage.Level.Error); + aMap.put(XML_VALUE_INCIDENT_FAIL, ITestMessage.Level.FatalError); + aMap.put(XML_VALUE_INCIDENT_XPASS, ITestMessage.Level.Error); + aMap.put(XML_VALUE_INCIDENT_UNKNOWN, ITestMessage.Level.FatalError); + // NOTE: Exception node is processed separately + STRING_INCIDENT_TO_MESSAGE_LEVEL = Collections.unmodifiableMap(aMap); + } + + /** Maps the metrics unit ids to the user readable names. */ + private static final Map XML_METRICS_TO_UNIT_NAME; + static { + Map aMap = new HashMap(); + aMap.put("events", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_events); //$NON-NLS-1$ + aMap.put("callgrind", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_instructions); //$NON-NLS-1$ + aMap.put("walltime", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_msec); //$NON-NLS-1$ + aMap.put("cputicks", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_ticks); //$NON-NLS-1$ + // NOTE: Exception node is processed separately + XML_METRICS_TO_UNIT_NAME = Collections.unmodifiableMap(aMap); + } + + /** The interface to notify the Tests Runner Core */ + private ITestModelUpdater modelUpdater; + + /** Stores the text between current XML tag. */ + private String elementData; + + /** Stores the text for currently parsed test message. */ + private String messageText; + + /** Stores the file name part of location for currently parsed test message. */ + private String fileName; + + /** Stores the line number part of location for currently parsed test message. */ + private int lineNumber; + + /** Stores the message level for currently parsed test message. */ + private ITestMessage.Level messageLevel; + + /** Stores the status for currently parsed test case. */ + private ITestItem.Status testCaseStatus; + + /** Stores the name for currently parsed test case. */ + private String testCaseName; + + /** Stores the currently parsing data tag. */ + private String currentDataTag; + + /** Stores the last parsed data tag. */ + private String lastDataTag; + + /** Stores whether the test case was already added (means Tests Runner Core notified). */ + private boolean testCaseAdded; + + + QtXmlLogHandler(ITestModelUpdater modelUpdater) { + this.modelUpdater = modelUpdater; + } + + /** + * Notifies about test case exiting (if it was entered). + */ + private void exitTestCaseIfNecessary() { + if (testCaseAdded) { + modelUpdater.setTestStatus(testCaseStatus); + modelUpdater.exitTestCase(); + testCaseAdded = false; + } + } + + /** + * Creates a new test case if a new data tag is met. + */ + private void createTestCaseIfNecessary() { + if (!lastDataTag.equals(currentDataTag)) { + exitTestCaseIfNecessary(); + currentDataTag = lastDataTag; + String suffix = !currentDataTag.isEmpty() ? MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_datatag_format, currentDataTag) : ""; //$NON-NLS-1$ + modelUpdater.enterTestCase(testCaseName+suffix); + testCaseAdded = true; + } + } + + /** + * Adds a new test message if there is a text for it. + */ + private void addTestMessageIfNecessary() { + if (messageText != null) { + modelUpdater.addTestMessage(fileName, lineNumber, messageLevel, messageText); + } + } + + /** + * Sets a new status for the currently parsing test case. + * + * @param newStatus new test status + * + * @note Passed status is set by default and should not be set explicitly. + * But in case of errors it should not override Failed or Skipped statuses. + */ + private void setCurrentTestCaseStatus(ITestItem.Status newStatus) { + // Passed status is set by default and should not be set explicitly. + // But in case of errors it should not override Failed or Skipped statuses. + if (newStatus != ITestItem.Status.Passed) { + testCaseStatus = newStatus; + } + } + + /** + * Converts the metric unit ids to user readable names. + * + * @param benchmarkMetric metric unit id + * @return user readable name + * @throws SAXException if metric unit id is not known + */ + private String getUnitsByBenchmarkMetric(String benchmarkMetric) throws SAXException { + String units = XML_METRICS_TO_UNIT_NAME.get(benchmarkMetric); + if (units == null) { + logAndThrowError(MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_unknown_benchmarck_metric, benchmarkMetric)); + } + return units; + } + + /** + * Converts the message level string to the internal enumeration core. + * + * @param map map to use + * @param incidentTypeStr message level string + * @return message level code + * @throws SAXException if message level string is not known + */ + private ITestMessage.Level getMessageLevel(Map map, String incidentTypeStr) throws SAXException { + Level result = map.get(incidentTypeStr); + if (result == null) { + logAndThrowError(MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_unknown_message_level, incidentTypeStr)); + } + return result; + } + + @Override + public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) throws SAXException { + + elementData = null; + if (qName == XML_NODE_TEST_CASE) { + // NOTE: Terminology mapping: Qt Test Case is actually a Test Suite + String testSuiteName = attrs.getValue(XML_ATTR_TEST_CASE_NAME); + modelUpdater.enterTestSuite(testSuiteName); + + } else if (qName == XML_NODE_TEST_FUNCTION) { + // NOTE: Terminology mapping: Qt Test Function is actually a Test Case + testCaseName = attrs.getValue(XML_ATTR_TEST_FUNCTION_NAME); + currentDataTag = null; + lastDataTag = ""; //$NON-NLS-1$ + testCaseAdded = false; + testCaseStatus = ITestItem.Status.Passed; + + } else if (qName == XML_NODE_MESSAGE) { + String messageLevelStr = attrs.getValue(XML_ATTR_TYPE); + fileName = attrs.getValue(XML_ATTR_FILE); + lineNumber = Integer.parseInt(attrs.getValue(XML_ATTR_LINE).trim()); + messageLevel = getMessageLevel(STRING_TO_MESSAGE_LEVEL, messageLevelStr); + messageText = null; + if (messageLevelStr.equals(XML_VALUE_MESSAGE_SKIP)) { + setCurrentTestCaseStatus(ITestCase.Status.Skipped); + } + + } else if (qName == XML_NODE_INCIDENT) { + String strType = attrs.getValue(XML_ATTR_TYPE); + fileName = attrs.getValue(XML_ATTR_FILE); + lineNumber = Integer.parseInt(attrs.getValue(XML_ATTR_LINE).trim()); + messageLevel = getMessageLevel(STRING_INCIDENT_TO_MESSAGE_LEVEL, strType); + messageText = null; + setCurrentTestCaseStatus(STRING_TO_TEST_STATUS.get(strType)); + + } else if (qName == XML_NODE_BENCHMARK) { + lastDataTag = attrs.getValue(XML_ATTR_DATA_TAG); + createTestCaseIfNecessary(); + int benchmarkResultIteratations = Integer.parseInt(attrs.getValue(XML_ATTR_BENCHMARK_ITERATIONS).trim()); + float benchmarkResultValue = Integer.parseInt(attrs.getValue(XML_ATTR_BENCHMARK_VALUE).trim()); + String units = getUnitsByBenchmarkMetric(attrs.getValue(XML_ATTR_BENCHMARK_METRIC).trim()); + modelUpdater.addTestMessage("", 0, ITestMessage.Level.Info, //$NON-NLS-1$ + MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_benchmark_result_message, + benchmarkResultValue/benchmarkResultIteratations, units, benchmarkResultValue, benchmarkResultIteratations + ) + ); + + } else if (qName == XML_NODE_DATATAG) { + lastDataTag = ""; //$NON-NLS-1$ + + } else if (qName == XML_NODE_DESCRIPTION + || qName == XML_NODE_ENVIRONMENT + || qName == XML_NODE_QTVERSION + || qName == XML_NODE_QTESTVERSION) { + /* just skip, do nothing */ + + } else { + logAndThrowErrorForElement(qName); + } + } + + @Override + public void endElement(String namespaceURI, String localName, String qName) throws SAXException { + + if (qName == XML_NODE_TEST_CASE) { + modelUpdater.exitTestSuite(); + + } else if (qName == XML_NODE_TEST_FUNCTION) { + createTestCaseIfNecessary(); + exitTestCaseIfNecessary(); + + } else if (qName == XML_NODE_DATATAG) { + lastDataTag = elementData; + + } else if (qName == XML_NODE_INCIDENT) { + createTestCaseIfNecessary(); + addTestMessageIfNecessary(); + + } else if (qName == XML_NODE_MESSAGE) { + createTestCaseIfNecessary(); + addTestMessageIfNecessary(); + + } else if (qName == XML_NODE_DESCRIPTION) { + messageText = elementData == null || elementData.isEmpty() ? "" : elementData; //$NON-NLS-1$ + + } else if (qName == XML_NODE_ENVIRONMENT + || qName == XML_NODE_QTVERSION + || qName == XML_NODE_QTESTVERSION + || qName == XML_NODE_BENCHMARK) { + /* just skip, do nothing */ + + } else { + logAndThrowErrorForElement(qName); + } + elementData = null; + } + + @Override + public void characters(char[] ch, int start, int length) { + StringBuilder sb = new StringBuilder(); + for (int i = start; i < start + length; i++) { + sb.append(ch[i]); + } + elementData = sb.toString(); + } + + /** + * Throws the testing exception for the specified XML tag. + * + * @param tagName XML tag name + * @throws SAXException the exception that will be thrown + */ + private void logAndThrowErrorForElement(String tagName) throws SAXException { + logAndThrowError( + MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_wrong_tag_name, tagName) + ); + } + + /** + * Throws the testing exception with the specified message. + * + * @param message the reason + * @throws SAXException the exception that will be thrown + */ + private void logAndThrowError(String message) throws SAXException { + SAXException e = new SAXException(message); + QtTestsRunnerPlugin.log(e); + throw e; + } + + @Override + public void warning(SAXParseException ex) throws SAXException { + QtTestsRunnerPlugin.log(ex); + } + + @Override + public void error(SAXParseException ex) throws SAXException { + QtTestsRunnerPlugin.log(ex); + throw ex; + } + + @Override + public void fatalError(SAXParseException ex) throws SAXException { + QtTestsRunnerPlugin.log(ex); + throw ex; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project new file mode 100644 index 00000000000..cc09c4417e7 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project @@ -0,0 +1,17 @@ + + + org.eclipse.cdt.testsrunner.source.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties new file mode 100644 index 00000000000..c6af93f4925 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties @@ -0,0 +1,5 @@ +bin.includes = feature.xml,\ + eclipse_update_120.jpg,\ + epl-v10.html,\ + feature.properties,\ + license.html diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/eclipse_update_120.jpg b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/eclipse_update_120.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfdf708ad617e4974cac04cc5c1c8192b09bbeb3 GIT binary patch literal 21695 zcmeHvcU)7=((p+_uhNSGp%(=Nr3wV321I%h5riZ_XrTltiYTH8C`eTiL3$Grle6uPge`61wfz> zKnMH-2t(wlntoUZ0MOS5!~g)G0LUSX01Sj6;2!|t1W0#b0I-Mb{{cHgM85GrK^`dp zjDh{&;{}o4g_%M4W+)aQ`Ia{W{A~pvuts93d%tREoIM6^=!C=Lyq$0!aCH;71=byn z^YsR#4K)C?^2G&J-q>`Y87Oib(yG`r#3&tBpmV+buZH7y1PEApjKiowyHxkU(Hi5-2G-83ief<_Jh+fRXSrN|CA=*)j2XUX~_f zj!rE)&M&}XTx);is8?{CI=Nts$=uL9%3Fptt@w(NMyx4Xvo0Mk%hql-j9GXRQs3b- zvZy5-mvQxJd_(8wrOc8SU8Bq94(F~VWR|-ORQhr>Gf{$CgY0`@~*!7=J4EGX}z^MYhV0my}9>e@je z(%I0OX0mw9@DCCGwFJUHMIiJ7G_c(|82|)Oi{wp>=YxfmePK;|DXQxvrWTTxXk~1? z^ePNXDHa!l9_K|0#ONA>QCtjCAX6X)DN1OqMP^*#<-32yEbpl-hv8E_ysyVYi|YpH z_wmj9%H}+7W~e)u2#VPZAEUWkNBy|qTxz9XGMk&Drkm^Fyow%MPMK>-bpS&Xm4?>n zmzf6^OG&vOu(&oW4*kxUCj|$xJaBDvD){)Bu9LyY#4lB;Z>8x;6}^~2QL_ncF9u9Pl}h7jCzp`Rxd_to{*TD39d(hOkDJ*i zaQgS}TVz;u%v%>46=lT9E%Ob%N{x-L^f9VqzLsoqEnjvduO#q^So|Ync**pr8uF!X zxE_04j3~UKD9p2<&!ElsQ{ltX{I#zi4U@I5is;!e>-gw`3S_M&wAY@v-p5J8s(U-% zc2->TfnQmrUXa$N(#enI2HWcfxoFNQ7sm;X&FBD2mwBX9lz+!(7W#)Kwwa$W{7=x~ z4WTm*3df)DozLSgI^m{&_G$NNv1cDelNL-Vkt8`;qC%=UqVSk=A??N-R~=~w$K)Dx zAKttcbRsA(NW`dN=dpj*X*px0Am%2aqxK{dpLF&!%ge*&saCMuwq)gF2WKff)+Y!+ zpxQ<=@*=-0Y@8i|*czp$>zyxjiO33kG#6Y_oWsHXHD|}8b$vxI-I+gvBcfg)ELJb4 zqN`kul*&ZBKrag^ZJya75C@M3vY`6TJ_kO>Gv2%;_|^9k?5mmE1=7?|qr7WZmhR8` zHe?MQI3>AiBp#a)qubs{=xksuN$>sO8>UnBbwm5}gCz0emy8dS7IrMu_lo+j(x+X} z4sLRdg|PD&s4cYwk#KmviuD=1J@xdnsq)CgWddMY5en^LeRiA;6OlwgQ$Dpx0M-Rf za+eer)Shv|-aXSM-^gJIxVkPiACSJHRH@TrKcN0v9E;@^gXA3%v&#ZRuVsg1N}CwR z*~~#5-$Nx32BpJ1euoNI{X7XkQ%*_rgDiRZFPqAaQEi7Oz8vomt+#r4?WwxfC6ZTz z@)T5?=FQ*>6VOBGsy*3?ymX7?4n;<|2CYpHY0gv9&!%wa#Wf-9*8!>%&7(TZR6_zo zjhCCv4>lF2mqcDt;EK1pq1WQBB1-D4ExJX zZ`tM#xEoY>gb5VbOnKQ`(8TDBq~v>ARjGF!DWFV@!O}huW@xN`PLf9?4g>PX zk@_TpyJPgeZzJ`OA0iDl^NqGQWf7-(;qVogn zx(<69q1a6mH34b?s=D`l(=j)Q{gs!Kn1mt0Xs@-zB&h#y4;5erxC3|q3qGy@20#Pi zfD}mku3aMU_wXz3d;agV-QQmsz7xI)Nld!?xVnNr#Kw@><9yuF-Ujy0C@}RcpD_wg zta`WYrl7axigR}a)4SmW#sU9p`Zylv_AN~m1u%AW`c5aN$-G^$D2%tc>j`f#1^H7w zq`Nc_%?Li^y9uPmFJ+TEdf|LL{)8gKd0`!~?ihC;H!u&4rU|ihgIye$rnU3ITh%_o!(2)KKOJk42g9i0acxteVo&J%1_x%(h76#CO4+Jr{3-7&|#LtpF z6W$${NQfK&StuA0)%NYJfj9v`P7R260oXye{kNn4+tL5B^4rn>?dbn@^nW}0|Cf&b z-Wfo>lTum{~gIA91kfiNC?ymukc{RJJRf6oC2)c1SRbUkTqM5;!kMNht*d16X=#k{#<}|JGRjFye&_ua{e$<^ zU-SNo{=xf`)yy4>SCRfE!#|+^JE{W*xxeo7@1q~l1mQ|xN>SYl1AaehfR74sb3**E zthkh%>G#bEapHCb_y+z1=l9I|I5gJ5|3At63+Io_;An}q!`uBw*?;BzUcj#C;FlRV z!m8}<@5(E;b> zW`|e7y4g8mB%M7lj!Ke0v41V^-p~!sl;E5x`C}F)+VTH=_+820((!L~{Z`lC(!k$h z{%u{q)%CYD@VA(MTi0)O{VfgrE#}|W^;=zkO9Ow4`L}ibR@dLsz~5s2ZC$_B^|v(e zx0wI8)u=Aa*Ek4}B9Y;^_qdsi_Y42APQP&#=qX1phV%| zE`>Z?2jlCC!Q;gZ!OayrFEm^o=jLJO?hgQaZ6@Xd7>T-tgG!c_QjnDumzE%&!1*5j zE%7_k|L{xf+dY;=quoA(u)g_;`c5Sd2lmtKx6_n2dgp%tqkk#2zIwS8oRr@gmwQ{J^a7S_KOTe zaL=wmfGJ}KV78S2_O&nru$eai2@^E{vrYynkRSbag3=t^WCQ>Up0Pc<2Vs!D8~-VS zMuADFH+J{H6rgTw3P<^Po!es}A^wm8RN&?%Gr$3G1N?vpcydh|kOPhZs(>b-3m5>V zz$w56K!MwsZh#ly3tRv$1J{5E;1&=MBmyZw29OIp0*Zk$;18e{cnQ1)FA#JAeZVJR z6qo|$fE8d9JgQC(p@lF(I3PR_LC8UfG(;Yv0?~w=fEYtgLC!)PA?^?#$OXt1NCYGX zk_btKwtZNO~ckn$Viw-;3VQC$4GQY%t%lqo+KAZZjdCB~+V43W%{?2yuu z9w0qPsz{0?wIp>U^(DPVnn0RGT0;7Qw2O3=ckm)k>4eMNM23ePCiP$MnO%%Lm^F}MPWtZP7zFz zK#@oBoT8m#jAD~=AEh9rBBcQ(n$n*#iZX+;lCp(zlyZ}bfl8Q4naY&Pnd&mt9jZrE zFR1#d7OAPJ`KT4Bji|BIm#FVhKc;S?9->~SVWbhGQKzw{@u7*N$)>5H`9QNsOG_(6 zt4eD{i>HmG&84lU9i&~OW1^FwL(-w?g6QtimD07-&C*lS3(~96+t3HlC(u8kZ=s*w zN4ZaEpZY$#eHZuL+gGu#XWudd6N40k0fQUE4Te01W`=P_az-IWO-3|h2xB^9J>v)y zjESE~oe9Nsg(-vS1=A=q8M81mlG&L#g1LbC9rGLuBg;`1a~40Adn{EfpIBk6Laazu zSJo)jV%Bcf4K^+|H8u=e7~3PZcD7aa{p_mj81``XLiR594GuVmCWi}0G)Ec704E8j z7^e}ZFK0663(o2N%=?e+N9_;aU%bEf0Q7*^0pkPb52PP>b6}Z^n@gL^gX=C=J=Zih zE4M1QGj|;KbM6TqCLR?YEKeLyHP0lR1+E5nh2McUz~^`m@apjT@TT&<39 z<}2hI;HTo3=Xcw6_XKj61ykXau9k@_8|7){ex|XNDnC- zazB)Is7IVeTuuC(c)s|M1gpdeiC~E`iCIYjNh`@{$wtYY!!n0m4`&?ilVX(8l?s-s zlvZ^G6RJ#T-pO`d)@fMqegWrcP#CR!-JS_L1y_oPgX} zxg@zBd1iS-`5W?03Zx3h6@nE0P*_)#Rm3Y6D}FsDe$3@q-m!5dVI_=GhSG>KpR%2D zs`4ilxXM|T2P&Tsya+o)8e&+LUlpyIr8=f2s^+ZrP;K`3;p1M%OOCIqE2;;o*J!{r zv^Byt-f1#wnrS9#4r=jfIcnu=&1uVMpVzL@A=S~-iPq^sav@R3T;!atoNl0QgC32Z ziC&`K@CmUKUMDK`q58V|vHJZd1y8!4EHeNMkOr{^1BSweo`%ni$czk)?iqbCmNLFz z+-SmNVr!CTvSNDNG|IHkOvKE`tj?U?+}b?XeAPn3BF5sArKDw`lAg6Vn|F50&cH6sZrL7b zpJYFWQb*lJO`%oMap(z*GA0Hy=Ai5l<1p^1>=^4f;e>EXaGJ)dV-vCS&N|L1&Z{m4 zF4-;wR}0rdHww42ZWZo~?k?^PIBuLDuFd11$2E^no{FCFo^xJ$URmA{?=#-zcxKR< zdgCMFbJb_)oXWX-=hl49eV_O-___PN@fY(C^B)V)3dlT9avpWQ?gHnQf^b-_PPD(&WStacLna=y1SL=l-PCe_`SlU z14&^?tM}3O+mlt3AEj`mM5Jsyz&?1Ns-0SzCX|+tPL_Ty{Y!>#mbsZQW+w?|ZC! zKD|f3AOGO`VZQfV?`Gene$xK%fqerBg9irFK8k)U{3QFSYDi<~&9KRE-w0}C>a+Lf ztaLCZjo=@*%sZd+|k?VC%A#9?tfl> zQw4p2y~}TVSIhpR82U57euQ6g60dqee-QptfbjG38+cpn=jAtg@bVkz)&gWu@B-J5 zKu$qMN|=DIk;p74<#<3W0&w-(W^>`PT&ZevFBxW`)EP+)S@||qh3@TwQVxOLngAp^D$`}rrw%b za@r^nGjj{h;=1976sy*uw$|8Z< zXj?eQ|G2yN^WvV4rIX+FJ2~Y|@5k2^kf*TzVRv&YnmUIo-BY<*?K4ZvTX=re=ARLS*4!L{xi_(-G=`DvXHEr))i2O*Ha@?y zZa6nCdxQD2SwKKyB+U)UQ<1FEq+=N)Rzc=!+nEI5`l=NRoXJcjP}If#^{{sQggjrO zmYCUPvIYhhZ+GnyUe#*xAg<{xRKh9iVok8WZ zd)8-F-nj6%e}aEIwCdARhi0dYSGL~ybm0`FKxC5Q+vSy>6FwjReG}SpZL?K2=vz?_ z<5*;lE=PBoC|Ia3?Yxdyh(x5WY+Pav7NgfPcW-_C!gQXCcI`}|_A@@KSL_W6Bt>}{ zk4X!b@jUT}p_!wRXGh`|#>aaFUI~V-;1A6V=H=y?*_OD>(Y6wR7xYgV2lI9$?zElY zRu)^}I%Yva`j($wfBi;O;nJt`c5{%cxe(d<6ztScpQe0$(t&VwrZ-_1l?*zJW2O{WzL#A?0zpf$wQTVx&XO#J8h&w z?u;1_?deuGSB!){F5gKz&e?DgzloHXC~DAcbUa$Hc=pnElED@lujh+(bnry7} zdV+l2V&_Qf8HDp}uOprScoqkQnFumjQ_~yFwCvjo3LE=ix|!r4e`tqXs?GD{_ zAw6y3+Aj18sH+Asm=JdfObrNM8l z8Wpd-zG1NRs%8S!8h>eqEB8J=+qtZvyMpTJ2i04LZf^7CTLhR_Z1dhfQ&_ioie>qa z42c5q@t~IatmHvcmQ0J$)`;bmCs~SL!B@a$b+)RfYO~OX(4MOxk>|(1?fEs8I<^%{ z?lI9w55!=|`lDw?>eEGThiZ-G9TpeI9J&<~LuO#Sqs?Zla*Y6tOy?~Giq*`GcT;lm zQOHmBZ)j&`449xA%NzV{oKk#OE~L%O(liK4v)vsmZv{ zWBs-6m3YO~6E9IbET+M{V(rrTCaUFFIQX)Q6ELN&(Z!d>Q^}J=1gXtx7YzuYxj9-2 zwJlC}h^@)S0aVTeKyKstyWGtuo;Mux5*+-|_Pxnk5@Yuk-oCB6Gv!a0ZEuh}E_Y1n zMhibHsv#*kEMY3s6x+BltqFSL>Li;5J*Y z%$(fOZnDjboR|kpWavOt8T-Mng&H*Q_Lt0JDg{) zd+}r0*7p7j?z*9p>iRK_rh;ZH*7iEWQHFG7Vru48VlJe#kWNb0@Z8z)>W&f+ZZVjUu{<2nHs&I*VP)VuVkaC z;&ji<*`(_A$-Oy*##c5~8ju9pE?33OQs^cg@EO_Pc+Gmb=wsd1AP=@3weTS%Vm2Rs zGaU(?%*?`bUaZdYHw-rD($2n;b3SxE-92%LUC^a9p~D$p%A}M1($f$T;(yU`-8{MK zz{Tm=ft+)1&BcQA6wuL>cM?=hufjD-1$O+wzL;hynX%A2m)Utq5h;cDW-OySN&v`B zsTcNpwwarn|KT3OB)So)fS5XeXC>!@k+WjXreZGlyMmjabKp_=J3$9h=2irZ!hMhw z55{BNn=P7;*j~;FijqUjT&-HasmjG_Z4x&Ahhq{4{aS?WmH}d(ds==;XDk$nOGOL? ztzMp~c+Svq>(eroK`H^T45}gkFSoOVl||LUm&q5Z=Ztoik~>a#T>QAWl*X$|e_P$a zbavw0wmoV}2vJ)sef8F{0Fg<{@yH@~*X#NTwwc{;f^?p-?r)skY@>O*BgzZ(%q2sf zw+yd4zAm&mwKjK``C{>n3ypU`6WLVW&*Md|_I!7`B6Q|z8NO0uBLJ|ksX*%zhskmJ zQ}bpe^1W9RV$!Uz%n|GZar^f#KvuGCGSkuE#VOxI8vEXlPb|>|@m8*i3(1Mnu*CVT zofbZ0JTW!baTLoeSS2UJBApg}KCaWhXyw}QplrUN_UqJa$rqc0^Y-XGc=!7S64asq zeQ}jlJiV7}YrW}bn{1uT>lBZ=|Cl{~{E$w0w;KPpj!ONpYyDTbJ_PKam5OljcW3tx zIuf;fp_1}QkbraX(S^GQ2NKU{3>y2p^xrGmxH7H4`aXQ)=`vT$sR*XnHr45itqMHl z;wCwzX@Nmsd1k8a_ti0IlAm7lThj6!9A|nu)}&B978|r$=n_YNGFEp@IIXC{%Wf;< zv0#Lk!pH<_n-bItZnkh9kf#fOBv6|>&eYs8dbgsSgaDNCe3e`IRG<>bQhGWos-9_` z=c{n9f21mx$aV9QNs@wko)uQaP;=QPZZ!oP#ht<(sIl|m%O`63>}5p97O;|N(pQg| zBmf9qK8}(0bk0iq(*!`10Qf&+2s%6S;f3wu_&Yc@`Q}I4FZX0hCpaB@%v4XRWQILc zxNKO0RQToot%Grmf71`z?+kOY*=nT?O_y{Yrk$&H!o!pSjLkoz=HLi2S(l ze5r0_R%(^i$wc{~FtyJfFP}zl>k@#_;;J@P4P8&fCjt;LUVk6G@AT<d- zyJ-JB5PIy2cVh78=GuyldzMVivIKzse9cf}hVk2m*jBl_ub)oWT8%`5gRb3L`D4(L z;+`bG%Q2pZq)y@vk4IkhdmQ*&P9Wkzy* zPW#h|=ju(Td;8}!zt(OM0Ijl3)J%+vNyjA*F8eT_;;3b}^_|dd+)DHeOZ@~*Ah{kN z*CDKlE@TOukQXd~s1@#-dr4hgZ820Lx3h#cpsD2BW*BS+GE}Q_w=Dj*IB7Su=XnEZwsK~akcrl|puF%M!vt!Ljaj0C z5*IU4mcQ=w?*y(TdQLtqGzxr%KI;fRYAN*_}umWBIVJ4x2@3ldt2-i@^d%PHBdJmch( z;LzRV%TdQ`=-n2gXRK%{7` zP!bSod)Q^C@I&X=%>AYf@s~}>qqlTa0m3lcIn}$F z$M|;hXyFXkKKH^t#`PG3>7gB_w!5o}c)cF*+b+c10iq@_cZiYz1gy524@F*y&OZXA zWoIS}yEq)Idj)5XBLKZQ5Bb<@cJkPR{Wi{@c!glP_%4L?9OGe{;VY?Q*>Wd8PHumV zXzFt0OqFJ9=3}(Ak6dadJI+{Q*&FPya`a)COz(^I zLy|3Jv%GAw3&;JUx3((ptR7^h<>>UDwbF(&Ni6`|=jZqu0pov}vd zo%O@_54AltQSz$$IOCz4Y0xt<4fhchsf(ngm}1Ax2ozT)4x)MEueZE@ogtUF3bWV* z$Tz#9s##wkC)n5NitegZYwncExnE4WSO~h7lC~+QQ#Tds+HF1sT;E98fZ}#){dw*M z70hN<`32=~+m24wy3|K)RCn#1eEejwF}HA;87Jd&sHZ75TD5<4)31@16;6 z-O1X|kQq0fn{`ov)PA=ttnWX+l9gWZw8SvyL3N?gC#Us9PMUJcgP>6!@upbYFy)q1BZ;U9&k`zzWb1J$pqWzLt!S|#BN zP}D0+BX#tvAHRmJFjhTZdsbPYsNIq=ixOuMIC-k>{r-EAq*1V~z^jrHQ`SrO@5DAL zBk(CUX6IOk^hXo3?Vgk_+f<5-7M<8}kFVFH5|xYPxtY*@vawAd)qa^?L=9J#lq*|f{GH5cK#F8%J)3B3+I}87wt1mNbL4YNZB_M$In%E;kDRFv zyqSM(y_VceQtN$$9zF6pn_1q07u;zrj8ECZ%7`bsx$t{z>exrsWfRbni2I%<-( z@v-vEn-%xA76xtZ^sQ}8-_vKh;%>4u2wDa#-3#U6400d_9`JAguuNu-L z13Yxh$Xn^>2tfFbepR&fto6x9NzfGD9^q(yp3{KBXAi_+!SpeoawaP|Ge^KEKo7H6 zWSkD{q))Jp-i>M%+eXSgE_*!scGM-YCyScN@JMUeV-vnx7>V2 zf)c)pm-;p4xtNB=1rPx(1{d&m4q_+qR$=` zLUoN*%*f~P_@tUzRDG+leUT}CZOe^>p}oz>_+^nvM@L;MDqN%!$V=Z2Q%Vl}%ys`E z>$$n!-nyc`mk-2p9sp+nMWKp-7?(~Y?R)SOX9dgNsIkCZwCS5wN$A-7a_H=3cgVdD zzsji{9h{dVkRVh8APP$bY){6Yp7b?UGgqe6%Dd-eQlKO#CdYE(oOivDqAX9(Jv~%Q zX%}!te=aCA)m5D92FmDR%4DPd+D6)=_GW%PrGiJNtOxFgRezp?tOTFK()sz*CG^=O zoNZVt&1iZpma#8(^nMI8EY??6DJb}3ujOzToII2}Waah}Oqse|oB$;E$`qmI6tKBY zIjIa?#sk9Xc{#UuL<6whIzHQ4nUKa$QO-iimLjbs+|QHMQ^`8Yl}MACoCa-dpX8n{ zQ@A?KDVs51>56fR=Fmgxv7AtS%;xkdw|o8>Lou5U+W=#4*8Zc)BV2r+pg#@G3o9GtQ<)R3{U%Jr_Z@{j+lB9~7H`SkRg=B9{60v#>;?glDd#CO7;O{iFHOs^4G+pJ zT-UbAUduPgJ&kzoEEv)8IkVp0KJ&aK8$*wUS+{tzEJ?>jNnDMbF9tVwN3l3d-J+T_9FPnbtRR@ZCUON_|I?h>(8dut>jUA{Gg7>-y(G zt_5qsQc5HD`H#eUK5BV&jQibd@q$|}(L2|-XI0K7i4p)^wv2Xa7Y_}+6qDGU!s7cP zQ)0M_ff3P){FTWiEy#(_;F8Cna=zwxI95z&60-7`itd(F?$qFFcO|$eF==%w?~4vx zD@GemYUJIrF}OjaPZ~hWcjU1di*V-WC&tsS447>cZ@w_$S(6@V3!TK}FfJ}_LvOAMccEFAf!fyaR8z(FV5*Y^^V2VY)+zcU;x7@>vJ6JE0N`D zckJKtR}ETVxe7P#Hp?NpdmgXEXmmHMz7L*`m5x6A{M;$O8FXX{jA^eSRhB<@UlVG6+&g20xt z1eI{dYN3h=gvqJ%i!;ZwHJ%J~S4>3uzqXET9O;cWI2kUK_&iYV7^_MbUq{+%z{n$& z{)unPJ6#3xQ=Xf)+)-Nd-40XsG*R_}%6UWw{Cu`SBX15YO0R#^ctom`-RX`$G(7J$w-uJO&FZ5O=jrXJQmRC} zzf4Uq`va2!-Q-xK9)@+5Ua6(tGtpz6nN1Aah2ZQ;KA + + + + + + + +Eclipse Public License - Version 1.0 + + + + + + +
+ +

Eclipse Public License - v 1.0 +

+ +

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER +THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, +REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE +OF THIS AGREEMENT.

+ +

1. DEFINITIONS

+ +

"Contribution" means:

+ +

a) +in the case of the initial Contributor, the initial code and documentation +distributed under this Agreement, and
+b) in the case of each subsequent Contributor:

+ +

i) +changes to the Program, and

+ +

ii) +additions to the Program;

+ +

where +such changes and/or additions to the Program originate from and are distributed +by that particular Contributor. A Contribution 'originates' from a Contributor +if it was added to the Program by such Contributor itself or anyone acting on +such Contributor's behalf. Contributions do not include additions to the +Program which: (i) are separate modules of software distributed in conjunction +with the Program under their own license agreement, and (ii) are not derivative +works of the Program.

+ +

"Contributor" means any person or +entity that distributes the Program.

+ +

"Licensed Patents " mean patent +claims licensable by a Contributor which are necessarily infringed by the use +or sale of its Contribution alone or when combined with the Program.

+ +

"Program" means the Contributions +distributed in accordance with this Agreement.

+ +

"Recipient" means anyone who +receives the Program under this Agreement, including all Contributors.

+ +

2. GRANT OF RIGHTS

+ +

a) +Subject to the terms of this Agreement, each Contributor hereby grants Recipient +a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly +display, publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and object code +form.

+ +

b) +Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free +patent license under Licensed Patents to make, use, sell, offer to sell, import +and otherwise transfer the Contribution of such Contributor, if any, in source +code and object code form. This patent license shall apply to the combination +of the Contribution and the Program if, at the time the Contribution is added +by the Contributor, such addition of the Contribution causes such combination +to be covered by the Licensed Patents. The patent license shall not apply to +any other combinations which include the Contribution. No hardware per se is +licensed hereunder.

+ +

c) +Recipient understands that although each Contributor grants the licenses to its +Contributions set forth herein, no assurances are provided by any Contributor +that the Program does not infringe the patent or other intellectual property +rights of any other entity. Each Contributor disclaims any liability to Recipient +for claims brought by any other entity based on infringement of intellectual +property rights or otherwise. As a condition to exercising the rights and +licenses granted hereunder, each Recipient hereby assumes sole responsibility +to secure any other intellectual property rights needed, if any. For example, +if a third party patent license is required to allow Recipient to distribute +the Program, it is Recipient's responsibility to acquire that license before +distributing the Program.

+ +

d) +Each Contributor represents that to its knowledge it has sufficient copyright +rights in its Contribution, if any, to grant the copyright license set forth in +this Agreement.

+ +

3. REQUIREMENTS

+ +

A Contributor may choose to distribute the +Program in object code form under its own license agreement, provided that: +

+ +

a) +it complies with the terms and conditions of this Agreement; and

+ +

b) +its license agreement:

+ +

i) +effectively disclaims on behalf of all Contributors all warranties and +conditions, express and implied, including warranties or conditions of title +and non-infringement, and implied warranties or conditions of merchantability +and fitness for a particular purpose;

+ +

ii) +effectively excludes on behalf of all Contributors all liability for damages, +including direct, indirect, special, incidental and consequential damages, such +as lost profits;

+ +

iii) +states that any provisions which differ from this Agreement are offered by that +Contributor alone and not by any other party; and

+ +

iv) +states that source code for the Program is available from such Contributor, and +informs licensees how to obtain it in a reasonable manner on or through a +medium customarily used for software exchange.

+ +

When the Program is made available in source +code form:

+ +

a) +it must be made available under this Agreement; and

+ +

b) a +copy of this Agreement must be included with each copy of the Program.

+ +

Contributors may not remove or alter any +copyright notices contained within the Program.

+ +

Each Contributor must identify itself as the +originator of its Contribution, if any, in a manner that reasonably allows +subsequent Recipients to identify the originator of the Contribution.

+ +

4. COMMERCIAL DISTRIBUTION

+ +

Commercial distributors of software may +accept certain responsibilities with respect to end users, business partners +and the like. While this license is intended to facilitate the commercial use +of the Program, the Contributor who includes the Program in a commercial +product offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes the +Program in a commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages and +costs (collectively "Losses") arising from claims, lawsuits and other +legal actions brought by a third party against the Indemnified Contributor to +the extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor +to control, and cooperate with the Commercial Contributor in, the defense and +any related settlement negotiations. The Indemnified Contributor may participate +in any such claim at its own expense.

+ +

For example, a Contributor might include the +Program in a commercial product offering, Product X. That Contributor is then a +Commercial Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance claims and +warranties are such Commercial Contributor's responsibility alone. Under this +section, the Commercial Contributor would have to defend claims against the +other Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages.

+ +

5. NO WARRANTY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS +AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, +WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely +responsible for determining the appropriateness of using and distributing the +Program and assumes all risks associated with its exercise of rights under this +Agreement , including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs or +equipment, and unavailability or interruption of operations.

+ +

6. DISCLAIMER OF LIABILITY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS +AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF +THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES.

+ +

7. GENERAL

+ +

If any provision of this Agreement is invalid +or unenforceable under applicable law, it shall not affect the validity or +enforceability of the remainder of the terms of this Agreement, and without +further action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable.

+ +

If Recipient institutes patent litigation +against any entity (including a cross-claim or counterclaim in a lawsuit) +alleging that the Program itself (excluding combinations of the Program with +other software or hardware) infringes such Recipient's patent(s), then such +Recipient's rights granted under Section 2(b) shall terminate as of the date +such litigation is filed.

+ +

All Recipient's rights under this Agreement +shall terminate if it fails to comply with any of the material terms or +conditions of this Agreement and does not cure such failure in a reasonable +period of time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use and +distribution of the Program as soon as reasonably practicable. However, +Recipient's obligations under this Agreement and any licenses granted by +Recipient relating to the Program shall continue and survive.

+ +

Everyone is permitted to copy and distribute +copies of this Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The Agreement +Steward reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement Steward has +the right to modify this Agreement. The Eclipse Foundation is the initial +Agreement Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each new version +of the Agreement will be given a distinguishing version number. The Program +(including Contributions) may always be distributed subject to the version of +the Agreement under which it was received. In addition, after a new version of +the Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly stated +in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to +the intellectual property of any Contributor under this Agreement, whether +expressly, by implication, estoppel or otherwise. All rights in the Program not +expressly granted under this Agreement are reserved.

+ +

This Agreement is governed by the laws of the +State of New York and the intellectual property laws of the United States of +America. No party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each party waives +its rights to a jury trial in any resulting litigation.

+ +

 

+ +
+ + + + \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties new file mode 100644 index 00000000000..25ff11f5aed --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties @@ -0,0 +1,168 @@ +############################################################################### +# Copyright (c) 2012 Anton Gorenkov and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - initial API and implementation +# Marc-Andre Laperle +############################################################################### +# feature.properties +# contains externalized strings for feature.xml +# "%foo" in feature.xml corresponds to the key "foo" in this file +# java.io.Properties file (ISO 8859-1 with "\" escapes) +# This file should be translated. + +# "featureName" property - name of the feature +featureName=C/C++ Unit Testing Support Source + +# "providerName" property - name of the company that provides the feature +providerName=Eclipse CDT + +# "updateSiteName" property - label for the update site +updateSiteName=Eclipse CDT Update Site + +# "description" property - description of the feature +description=Support for running unit tests. Source code. + +# copyright +copyright=\ +Copyright (c) 2012 Anton Gorenkov and others.\n\ +All rights reserved. This program and the accompanying materials\n\ +are made available under the terms of the Eclipse Public License v1.0\n\ +which accompanies this distribution, and is available at\n\ +http://www.eclipse.org/legal/epl-v10.html + +# "licenseURL" property - URL of the "Feature License" +# do not translate value - just change to point to a locale-specific HTML page +licenseURL=license.html + +# "license" property - text of the "Feature Update License" +# should be plain text version of license agreement pointed to be "licenseURL" +license=\ +Eclipse Foundation Software User Agreement\n\ +February 1, 2011\n\ +\n\ +Usage Of Content\n\ +\n\ +THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\ +OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\ +USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\ +AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\ +NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\ +AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\ +AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\ +OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\ +TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\ +OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\ +BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\ +\n\ +Applicable Licenses\n\ +\n\ +Unless otherwise indicated, all Content made available by the\n\ +Eclipse Foundation is provided to you under the terms and conditions of\n\ +the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\ +provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\ +For purposes of the EPL, "Program" will mean the Content.\n\ +\n\ +Content includes, but is not limited to, source code, object code,\n\ +documentation and other files maintained in the Eclipse Foundation source code\n\ +repository ("Repository") in software modules ("Modules") and made available\n\ +as downloadable archives ("Downloads").\n\ +\n\ + - Content may be structured and packaged into modules to facilitate delivering,\n\ + extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\ + plug-in fragments ("Fragments"), and features ("Features").\n\ + - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\ + in a directory named "plugins".\n\ + - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\ + Each Feature may be packaged as a sub-directory in a directory named "features".\n\ + Within a Feature, files named "feature.xml" may contain a list of the names and version\n\ + numbers of the Plug-ins and/or Fragments associated with that Feature.\n\ + - Features may also include other Features ("Included Features"). Within a Feature, files\n\ + named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\ +\n\ +The terms and conditions governing Plug-ins and Fragments should be\n\ +contained in files named "about.html" ("Abouts"). The terms and\n\ +conditions governing Features and Included Features should be contained\n\ +in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\ +Licenses may be located in any directory of a Download or Module\n\ +including, but not limited to the following locations:\n\ +\n\ + - The top-level (root) directory\n\ + - Plug-in and Fragment directories\n\ + - Inside Plug-ins and Fragments packaged as JARs\n\ + - Sub-directories of the directory named "src" of certain Plug-ins\n\ + - Feature directories\n\ +\n\ +Note: if a Feature made available by the Eclipse Foundation is installed using the\n\ +Provisioning Technology (as defined below), you must agree to a license ("Feature \n\ +Update License") during the installation process. If the Feature contains\n\ +Included Features, the Feature Update License should either provide you\n\ +with the terms and conditions governing the Included Features or inform\n\ +you where you can locate them. Feature Update Licenses may be found in\n\ +the "license" property of files named "feature.properties" found within a Feature.\n\ +Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\ +terms and conditions (or references to such terms and conditions) that\n\ +govern your use of the associated Content in that directory.\n\ +\n\ +THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\ +TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\ +SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ +\n\ + - Eclipse Distribution License Version 1.0 (available at http://www.eclipse.org/licenses/edl-v1.0.html)\n\ + - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ + - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ + - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ + - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ + - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ +\n\ +IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ +TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\ +is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\ +govern that particular Content.\n\ +\n\ +\n\Use of Provisioning Technology\n\ +\n\ +The Eclipse Foundation makes available provisioning software, examples of which include,\n\ +but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\ +the purpose of allowing users to install software, documentation, information and/or\n\ +other materials (collectively "Installable Software"). This capability is provided with\n\ +the intent of allowing such users to install, extend and update Eclipse-based products.\n\ +Information about packaging Installable Software is available at\n\ +http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\ +\n\ +You may use Provisioning Technology to allow other parties to install Installable Software.\n\ +You shall be responsible for enabling the applicable license agreements relating to the\n\ +Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\ +in accordance with the Specification. By using Provisioning Technology in such a manner and\n\ +making it available in accordance with the Specification, you further acknowledge your\n\ +agreement to, and the acquisition of all necessary rights to permit the following:\n\ +\n\ + 1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\ + the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\ + extending or updating the functionality of an Eclipse-based product.\n\ + 2. During the Provisioning Process, the Provisioning Technology may cause third party\n\ + Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\ + 3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\ + govern the use of the Installable Software ("Installable Software Agreement") and such\n\ + Installable Software Agreement shall be accessed from the Target Machine in accordance\n\ + with the Specification. Such Installable Software Agreement must inform the user of the\n\ + terms and conditions that govern the Installable Software and must solicit acceptance by\n\ + the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\ + indication of agreement by the user, the provisioning Technology will complete installation\n\ + of the Installable Software.\n\ +\n\ +Cryptography\n\ +\n\ +Content may contain encryption software. The country in which you are\n\ +currently may have restrictions on the import, possession, and use,\n\ +and/or re-export to another country, of encryption software. BEFORE\n\ +using any encryption software, please check the country's laws,\n\ +regulations and policies concerning the import, possession, or use, and\n\ +re-export of encryption software, to see if this is permitted.\n\ +\n\ +Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n +########### end of license property ########################################## diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml new file mode 100644 index 00000000000..4c3d0957f9b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml @@ -0,0 +1,51 @@ + + + + + %description + + + + %copyright + + + + %license + + + + + + + + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html new file mode 100644 index 00000000000..f19c483b9c8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html @@ -0,0 +1,108 @@ + + + + + +Eclipse Foundation Software User Agreement + + + +

Eclipse Foundation Software User Agreement

+

February 1, 2011

+ +

Usage Of Content

+ +

THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE + OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR + NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND + CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.

+ +

Applicable Licenses

+ +

Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 + ("EPL"). A copy of the EPL is provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html. + For purposes of the EPL, "Program" will mean the Content.

+ +

Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").

+ +
    +
  • Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").
  • +
  • Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".
  • +
  • A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + and/or Fragments associated with that Feature.
  • +
  • Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.
  • +
+ +

The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +including, but not limited to the following locations:

+ +
    +
  • The top-level (root) directory
  • +
  • Plug-in and Fragment directories
  • +
  • Inside Plug-ins and Fragments packaged as JARs
  • +
  • Sub-directories of the directory named "src" of certain Plug-ins
  • +
  • Feature directories
  • +
+ +

Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in +that directory.

+ +

THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE +OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):

+ + + +

IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please +contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.

+ + +

Use of Provisioning Technology

+ +

The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at http://eclipse.org/equinox/p2/repository_packaging.html + ("Specification").

+ +

You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the + applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology + in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the + Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:

+ +
    +
  1. A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + product.
  2. +
  3. During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be + accessed and copied to the Target Machine.
  4. +
  5. Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern + the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such + indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.
  6. +
+ +

Cryptography

+ +

Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to + another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import, + possession, or use, and re-export of encryption software, to see if this is permitted.

+ +

Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.

+ + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml new file mode 100644 index 00000000000..8bf6a1228c1 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 8.1.0-SNAPSHOT + ../../pom.xml + + + org.eclipse.cdt.features + 7.0.0-SNAPSHOT + org.eclipse.cdt.testsrunner.source.feature + eclipse-feature + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.test/.classpath new file mode 100644 index 00000000000..ad32c83a788 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/.project b/testsrunner/org.eclipse.cdt.testsrunner.test/.project new file mode 100644 index 00000000000..fcfb09a776e --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/.project @@ -0,0 +1,28 @@ + + + org.eclipse.cdt.testsrunner.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0e860bfc279 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,82 @@ +#Mon Apr 16 13:01:24 EEST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..8753f5de416 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.cdt.testsrunner.test +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.cdt.testsrunner.test.TestsRunnerTestActivator +Require-Bundle: org.junit, + org.eclipse.core.runtime, + org.eclipse.cdt.core.tests, + org.eclipse.cdt.testsrunner;bundle-version="7.0.0", + org.eclipse.cdt.testsrunner.boost;bundle-version="7.0.0", + org.eclipse.cdt.testsrunner.qttest;bundle-version="7.0.0", + org.eclipse.cdt.testsrunner.gtest;bundle-version="7.0.0" +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-Vendor: %Bundle-Vendor diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties b/testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties new file mode 100644 index 00000000000..c93c6763da9 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +#Properties file for org.eclipse.cdt.testsrunner.test +Bundle-Name = C/C++ Development Tools Tests Running Support Tests +Bundle-Vendor = Eclipse CDT \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/about.html b/testsrunner/org.eclipse.cdt.testsrunner.test/about.html new file mode 100644 index 00000000000..d7c511887d6 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/about.html @@ -0,0 +1,24 @@ + + +About + + +

About This Content

+ +

June 22, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties new file mode 100644 index 00000000000..67172946998 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + src/,\ + OSGI-INF/,\ + test.xml,\ + about.html +jre.compilation.profile = J2SE-1.5 +src.includes = about.html diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml new file mode 100644 index 00000000000..0606be04322 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 8.1.0-SNAPSHOT + ../../pom.xml + + + 1.0.0-SNAPSHOT + org.eclipse.cdt.testsrunner.test + eclipse-test-plugin + + + + cdt.repo + file:/${basedir}/../../releng/org.eclipse.cdt.repo/target/repository + p2 + + + + + + + org.eclipse.tycho + tycho-surefire-plugin + ${tycho-version} + + true + + **/TestsRunnerSuite.* + + true + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java new file mode 100644 index 00000000000..5d9713be595 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.core; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.eclipse.cdt.testsrunner.internal.model.TestModelManager; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestSuite; + + +/** + * Base test case for test suites & test cases reordering in TestModelManager. + */ +@SuppressWarnings("nls") +public abstract class TestModelManagerBaseReorderingTestCase extends TestCase { + + protected TestModelManager modelManager; + protected List expectedSuitesOrder = new ArrayList(); + + + protected abstract ITestSuite createTestsHierarchy(); + + protected abstract void visitTestItem(String name); + + + @Override + protected void setUp() throws Exception { + super.setUp(); + modelManager = new TestModelManager(createTestsHierarchy(), false); + modelManager.testingStarted(); + } + + @Override + protected void tearDown() throws Exception { + modelManager.testingFinished(); + ITestItem[] rootTestSuiteChildren = modelManager.getRootSuite().getChildren(); + assertEquals("Unexpected children count", expectedSuitesOrder.size(), rootTestSuiteChildren.length); + for (int i = 0; i < rootTestSuiteChildren.length; i++) { + assertEquals("Unexpected child name", expectedSuitesOrder.get(i), rootTestSuiteChildren[i].getName()); + } + } + + private void visitTestItemWithExpectation(String name) { + visitTestItem(name); + expectedSuitesOrder.add(name); + } + + public void testNoReordering() { + visitTestItemWithExpectation("item1"); + visitTestItemWithExpectation("item2"); + visitTestItemWithExpectation("item3"); + } + + public void testItemAdd() { + visitTestItemWithExpectation("item1"); + visitTestItemWithExpectation("itemNew"); + visitTestItemWithExpectation("item2"); + visitTestItemWithExpectation("item3"); + } + + public void testItemAddToBeginAndEnd() { + visitTestItemWithExpectation("itemNew"); + visitTestItemWithExpectation("item1"); + visitTestItemWithExpectation("item2"); + visitTestItemWithExpectation("item3"); + visitTestItemWithExpectation("itemNew2"); + } + + public void testItemRemove() { + visitTestItemWithExpectation("item1"); + visitTestItemWithExpectation("item3"); + } + + public void testItemRemoveFromBeginAndEnd() { + visitTestItemWithExpectation("item2"); + } + + public void testItemRemoveAndAdd() { + visitTestItemWithExpectation("item1"); + visitTestItemWithExpectation("itemNew"); + visitTestItemWithExpectation("item3"); + } + + public void testItemOrderChange() { + visitTestItemWithExpectation("item1"); + visitTestItemWithExpectation("item3"); + visitTestItemWithExpectation("item2"); + } + + public void testItemReverse() { + visitTestItemWithExpectation("item3"); + visitTestItemWithExpectation("item2"); + visitTestItemWithExpectation("item1"); + } + + public void testItemVisitTwice() { + visitTestItem("item1"); + visitTestItemWithExpectation("item2"); + visitTestItemWithExpectation("item1"); + visitTestItem("item3"); + visitTestItemWithExpectation("item3"); + } + + public void testItemVisitTwiceAndReorder() { + visitTestItem("item3"); + visitTestItemWithExpectation("item1"); + visitTestItemWithExpectation("item3"); + visitTestItemWithExpectation("item2"); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java new file mode 100644 index 00000000000..31c382eaa2e --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.core; + +import org.eclipse.cdt.testsrunner.internal.model.TestCase; +import org.eclipse.cdt.testsrunner.internal.model.TestModelManager; +import org.eclipse.cdt.testsrunner.internal.model.TestSuite; +import org.eclipse.cdt.testsrunner.model.ITestSuite; + + +/** + * Tests on the test cases reordering in TestModelManager. + */ +@SuppressWarnings("nls") +public class TestModelManagerCasesReorderingTestCase extends TestModelManagerBaseReorderingTestCase { + + @Override + protected ITestSuite createTestsHierarchy() { + TestSuite rootTestSuite = new TestSuite(TestModelManager.ROOT_TEST_SUITE_NAME, null); + rootTestSuite.getChildrenList().add(new TestCase("item1", rootTestSuite)); + rootTestSuite.getChildrenList().add(new TestCase("item2", rootTestSuite)); + rootTestSuite.getChildrenList().add(new TestCase("item3", rootTestSuite)); + return rootTestSuite; + } + + @Override + protected void visitTestItem(String name) { + modelManager.enterTestCase(name); + modelManager.exitTestCase(); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java new file mode 100644 index 00000000000..3a1332e342e --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.core; + +import org.eclipse.cdt.testsrunner.internal.model.TestModelManager; +import org.eclipse.cdt.testsrunner.internal.model.TestSuite; +import org.eclipse.cdt.testsrunner.model.ITestSuite; + + +/** + * Tests on the test suites reordering in TestModelManager. + */ +@SuppressWarnings("nls") +public class TestModelManagerSuitesReorderingTestCase extends TestModelManagerBaseReorderingTestCase { + + @Override + protected ITestSuite createTestsHierarchy() { + TestSuite rootTestSuite = new TestSuite(TestModelManager.ROOT_TEST_SUITE_NAME, null); + rootTestSuite.getChildrenList().add(new TestSuite("item1", rootTestSuite)); + rootTestSuite.getChildrenList().add(new TestSuite("item2", rootTestSuite)); + rootTestSuite.getChildrenList().add(new TestSuite("item3", rootTestSuite)); + return rootTestSuite; + } + + @Override + protected void visitTestItem(String name) { + modelManager.enterTestSuite(name); + modelManager.exitTestSuite(); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java new file mode 100644 index 00000000000..1d4b2499315 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.test; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.cdt.testsrunner.core.TestModelManagerCasesReorderingTestCase; +import org.eclipse.cdt.testsrunner.core.TestModelManagerSuitesReorderingTestCase; +import org.eclipse.cdt.testsrunner.testsrunners.BoostTestCase; +import org.eclipse.cdt.testsrunner.testsrunners.GoogleTestCase; +import org.eclipse.cdt.testsrunner.testsrunners.QtTestCase; + + +/** + * Test suite with all the tests on Tests Runner. + */ +public class TestsRunnerSuite extends TestSuite { + + public TestsRunnerSuite() { + } + + public TestsRunnerSuite(Class theClass, String name) { + super(theClass, name); + } + + public TestsRunnerSuite(Class theClass) { + super(theClass); + } + + public TestsRunnerSuite(String name) { + super(name); + } + + public static Test suite() { + final TestsRunnerSuite suite = new TestsRunnerSuite(); + // Core + suite.addTestSuite(TestModelManagerSuitesReorderingTestCase.class); + suite.addTestSuite(TestModelManagerCasesReorderingTestCase.class); + // Tests Runners Plug-ins + suite.addTestSuite(BoostTestCase.class); + suite.addTestSuite(GoogleTestCase.class); + suite.addTestSuite(QtTestCase.class); + return suite; + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java new file mode 100644 index 00000000000..375b7500b44 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.test; + +import org.eclipse.core.runtime.Plugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class TestsRunnerTestActivator extends Plugin { + + /** The plug-in ID .*/ + public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.test"; //$NON-NLS-1$ + + /** Plug-in instance. */ + private static TestsRunnerTestActivator plugin; + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared plug-in instance. + * + * @return the plug-in instance + */ + public static TestsRunnerTestActivator getDefault() { + return plugin; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java new file mode 100644 index 00000000000..1d6be7e13c1 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.testsrunners; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import junit.framework.TestCase; + +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.TestingException; +import org.eclipse.cdt.testsrunner.test.TestsRunnerTestActivator; +import org.eclipse.core.runtime.Plugin; + + +/** + * Base test case for Tests Runner provider plug-ins testing. + */ +@SuppressWarnings("nls") +public abstract class BaseTestCase extends TestCase { + + protected static final String EOL = System.getProperty("line.separator"); + + protected MockTestModelUpdater mockModelUpdater = new MockTestModelUpdater(); + protected ITestsRunnerProvider testsRunner = createTestsRunner(); + protected boolean expectTestingException = false; + + + protected abstract ITestsRunnerProvider createTestsRunner(); + + protected String getAboveComment() { + return getContents(1)[0].toString(); + } + + private StringBuilder[] getContents(int sections) { + try { + return TestSourceReader.getContentsForTest(getPlugin().getBundle(), getSourcePrefix(), getClass(), getName(), sections); + } catch (IOException e) { + fail(e.getMessage()); + return null; + } + } + + protected Plugin getPlugin() { + return TestsRunnerTestActivator.getDefault(); + } + + protected String getSourcePrefix() { + return "src"; + } + + protected void runTestsRunner() throws TestingException { + try { + mockModelUpdater.replay(); + String inputString = getAboveComment(); + InputStream inStream = new ByteArrayInputStream(inputString.getBytes("UTF-8")); + boolean testingExceptionHappen = false; + String exceptionMessage = null; + try { + testsRunner.run(mockModelUpdater, inStream); + + } catch (TestingException e) { + testingExceptionHappen = true; + exceptionMessage = e.getMessage(); + } + if (expectTestingException != testingExceptionHappen) { + if (testingExceptionHappen) { + fail("Unexpected exception: "+exceptionMessage); + } else { + fail("TestingException is expected, but did not happen!"); + } + } + + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + + protected void expectTestingException() { + expectTestingException = true; + } + + @Override + protected void tearDown() throws Exception { + runTestsRunner(); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java new file mode 100644 index 00000000000..053a5ea553c --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java @@ -0,0 +1,481 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.testsrunners; + +import org.eclipse.cdt.testsrunner.internal.boost.BoostTestsRunnerProvider; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestMessage; + + +/** + * Tests for {@see BoostTestsRunner} class + */ +@SuppressWarnings("nls") +public class BoostTestCase extends BaseTestCase { + + private static final String DEFAULT_LOCATION_FILE = null; + private static final int DEFAULT_LOCATION_LINE = -1; + private static final String EXCEPTION_CHECKPOINT_SUFFIX = "\nLast check point was here."; + + @Override + public ITestsRunnerProvider createTestsRunner() { + return new BoostTestsRunnerProvider(); + } + + + // + // + // + // + // + public void testTheOnlyTestCase() { + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("test"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // + // + // + // + public void testAFewTestCases() { + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("test1"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test2"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test3"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // + // + public void testEmptyTestSuite() { + // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestSuite("InnerTS"); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // + // + // + // + // + // + public void testAFewTestCasesInTestSuite() { + // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestSuite("InnerTS"); + mockModelUpdater.enterTestCase("test1"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test2"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test3"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // + // + // + // + public void testEmptyTestSuiteInTestSuite() { + // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestSuite("InnerTS"); + mockModelUpdater.enterTestSuite("InnerInnerTS"); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testSimpleTestsHierarchy() { + // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestSuite("InnerTS"); + mockModelUpdater.enterTestSuite("InnerInnerTS"); + mockModelUpdater.enterTestCase("test1"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.enterTestCase("test2"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test3"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.enterTestCase("test4"); + mockModelUpdater.exitTestCase(); + } + + + // + // + // + // check 1 passed + // + // + // condition 0 is not satisfied + // Test case testPassWithWarning did not run any assertions + // + // + // Test case testPassIfEmpty did not run any assertions + // + // + // check 0 failed + // check 1 passed + // + // + // critical check 0 failed + // + // + // unknown type + // + // + // memory access violation at address: 0x00000000: no mapping at fault address + // Test is aborted + // + // + // + public void testDifferentTestStatuses() { + mockModelUpdater.skipCalls("addTestMessage"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("testPass"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testPassWithWarning"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testPassIfEmpty"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testFailWithCheck"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testFailWithRequire"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testAbortedOnException"); + mockModelUpdater.setTestStatus(ITestItem.Status.Aborted); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testAbortedOnNullDereference"); + mockModelUpdater.setTestStatus(ITestItem.Status.Aborted); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // + // + // + // + // + public void testEmptyMessage() { + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("test"); + mockModelUpdater.addTestMessage("file.cpp", 22, ITestMessage.Level.Info, ""); + mockModelUpdater.addTestMessage("file2.cpp", 47, ITestMessage.Level.Exception, EXCEPTION_CHECKPOINT_SUFFIX); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // Custom warning + // Exception message end + // + // + // + public void testSpacesInBeginAndEndOfMessage() { + // NOTE: Last checkpoint tag cannot be in the middle of exception (at least, for current version of Boost), but we check it anyway + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("test"); + mockModelUpdater.addTestMessage("file", 42, ITestMessage.Level.Warning, " Custom warning "); + mockModelUpdater.addTestMessage("file2", 47, ITestMessage.Level.Exception, " Exception message end "+EXCEPTION_CHECKPOINT_SUFFIX); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // Custom warning + // Exceptions should be located by pass point + // + // + // + public void testMessageWithoutLocation() { + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("test"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, "Custom warning"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Exceptions should be located by pass point"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // No line number + // Empty file name + // No file name + // Exception without line number + // Exception with empty file name + // Exception without file name + // + // + // + public void testMessageWithLocation() { + // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("test"); + mockModelUpdater.addTestMessage("file.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, "No line number"); + mockModelUpdater.addTestMessage("", 1, ITestMessage.Level.Warning, "Empty file name"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 2, ITestMessage.Level.Warning, "No file name"); + // NOTE: Last check point is not available, so EXCEPTION_CHECKPOINT_SUFFIX should not be added + mockModelUpdater.addTestMessage("file2.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Exception without line number"); + mockModelUpdater.addTestMessage("", 3, ITestMessage.Level.Exception, "Exception with empty file name"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 4, ITestMessage.Level.Exception, "Exception without file name"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // Message with location + // Message without location + // + // + // Exception with location + // Exception without location + // + // + // Another message with location + // Another exception without location + // + // + // Another exception with location + // Another message without location + // + // + // + public void testMessagesWithAndWithoutLocation() { + // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("test1"); + mockModelUpdater.addTestMessage("file1.cpp", 1, ITestMessage.Level.Error, "Message with location"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Message without location"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test2"); + mockModelUpdater.addTestMessage("file2.cpp", 2, ITestMessage.Level.Exception, "Exception with location"+EXCEPTION_CHECKPOINT_SUFFIX); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Exception without location"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test3"); + mockModelUpdater.addTestMessage("file3.cpp", 3, ITestMessage.Level.Error, "Another message with location"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Another exception without location"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("test4"); + mockModelUpdater.addTestMessage("file4.cpp", 4, ITestMessage.Level.Exception, "Another exception with location"+EXCEPTION_CHECKPOINT_SUFFIX); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Another message without location"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // check 1 passed + // 1000 + // + // + // critical check 0 failed + // 2000 + // + // + // exception message + // 3000 + // + // + // another exception message + // Test is aborted + // 4000 + // + // + // yet another exception message + // 5000 + // + // + // + public void testExecutionTimePresence() { + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("testPass"); + mockModelUpdater.addTestMessage("file.cpp", 22, ITestMessage.Level.Info, "check 1 passed"); + mockModelUpdater.setTestingTime(1); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testFail"); + mockModelUpdater.addTestMessage("file2.cpp", 38, ITestMessage.Level.FatalError, "critical check 0 failed"); + mockModelUpdater.setTestingTime(2); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testAbortedOnException"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "exception message"); + mockModelUpdater.setTestingTime(3); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testAbortedOnNullDereference"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "another exception message"); + mockModelUpdater.addTestMessage("file3.h", 164, ITestMessage.Level.Message, "Test is aborted"); + mockModelUpdater.setTestingTime(4); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testAbortedOnExceptionWithLocation"); + mockModelUpdater.addTestMessage("file4.cpp", 47, ITestMessage.Level.Exception, "yet another exception message"+EXCEPTION_CHECKPOINT_SUFFIX); + mockModelUpdater.setTestingTime(5); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + public void testNoInput() { + // NOTE: The comment above is left blank intentionally + expectTestingException(); + } + + + // + // + // + // + // + // + public void testBadFormedXml() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + + + // + // + // + public void testUnexceptedXmlEnd() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + + + // + // + // + // check 1 passed + // 100 + // + // + // + public void testUnexpectedXmlElement() { + mockModelUpdater.skipCalls("enterTestSuite"); + expectTestingException(); + } + + + // + // + // + // check 1 passed + // + // + // + public void testWrongLineNumberValue() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + + + // + // + // + // wrong value + // + // + // + public void testWrongExecutionTimeValue() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java new file mode 100644 index 00000000000..ef561b6ae79 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java @@ -0,0 +1,698 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.testsrunners; + +import org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerProvider; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestMessage; + + +/** + * Tests for {@see GoogleTestsRunner} class + */ +@SuppressWarnings("nls") +public class GoogleTestCase extends BaseTestCase { + + private static final String DEFAULT_LOCATION_FILE = null; + private static final int DEFAULT_LOCATION_LINE = 1; + + @Override + protected ITestsRunnerProvider createTestsRunner() { + return new GoogleTestsRunnerProvider(); + } + + //Running main() from gtest_main.cc + //[==========] Running 0 tests from 0 test cases. + //[==========] 0 tests from 0 test cases ran. (0 ms total) + //[ PASSED ] 0 tests. + public void testNoTestCases() { + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.DemoTest + //[ OK ] DemoTestCase.DemoTest (0 ms) + //[----------] 1 test from DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 1 test. + public void testTheOnlyTestCase() { + mockModelUpdater.skipCalls("setTestStatus"); + mockModelUpdater.skipCalls("setTestingTime"); + + mockModelUpdater.enterTestSuite("DemoTestCase"); + mockModelUpdater.enterTestCase("DemoTest"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 3 tests from 1 test case. + //[----------] Global test environment set-up. + //[----------] 3 tests from DemoTestCase + //[ RUN ] DemoTestCase.DemoTest1 + //[ OK ] DemoTestCase.DemoTest1 (0 ms) + //[ RUN ] DemoTestCase.DemoTest2 + //[ OK ] DemoTestCase.DemoTest2 (0 ms) + //[ RUN ] DemoTestCase.DemoTest3 + //[ OK ] DemoTestCase.DemoTest3 (0 ms) + //[----------] 3 tests from DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 3 tests from 1 test case ran. (0 ms total) + //[ PASSED ] 3 tests. + public void testAFewTestCasesInTheOnlyTestSuites() { + mockModelUpdater.skipCalls("setTestStatus"); + mockModelUpdater.skipCalls("setTestingTime"); + + mockModelUpdater.enterTestSuite("DemoTestCase"); + mockModelUpdater.enterTestCase("DemoTest1"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("DemoTest2"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("DemoTest3"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 2 tests from 2 test cases. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.DemoTest + //[ OK ] DemoTestCase.DemoTest (0 ms) + //[----------] 1 test from DemoTestCase (0 ms total) + // + //[----------] 1 test from DemoTestCase2 + //[ RUN ] DemoTestCase2.DemoTest2 + //[ OK ] DemoTestCase2.DemoTest2 (0 ms) + //[----------] 1 test from DemoTestCase2 (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 2 tests from 2 test cases ran. (0 ms total) + //[ PASSED ] 2 tests. + public void testTheOnlyTestCasesInAFewTestSuites() { + mockModelUpdater.skipCalls("setTestStatus"); + mockModelUpdater.skipCalls("setTestingTime"); + + mockModelUpdater.enterTestSuite("DemoTestCase"); + mockModelUpdater.enterTestCase("DemoTest"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.enterTestSuite("DemoTestCase2"); + mockModelUpdater.enterTestCase("DemoTest2"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 4 tests from 2 test cases. + //[----------] Global test environment set-up. + //[----------] 2 tests from DemoTestCase1 + //[ RUN ] DemoTestCase1.DemoTest1 + //[ OK ] DemoTestCase1.DemoTest1 (0 ms) + //[ RUN ] DemoTestCase1.DemoTest2 + //[ OK ] DemoTestCase1.DemoTest2 (0 ms) + //[----------] 2 tests from DemoTestCase1 (0 ms total) + // + //[----------] 2 tests from DemoTestCase2 + //[ RUN ] DemoTestCase2.DemoTest1 + //[ OK ] DemoTestCase2.DemoTest1 (0 ms) + //[ RUN ] DemoTestCase2.DemoTest2 + //[ OK ] DemoTestCase2.DemoTest2 (0 ms) + //[----------] 2 tests from DemoTestCase2 (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 4 tests from 2 test cases ran. (0 ms total) + //[ PASSED ] 4 tests. + public void testAFewTestCasesWithTheSameNameInDifferentTestSuites() { + mockModelUpdater.skipCalls("setTestStatus"); + mockModelUpdater.skipCalls("setTestingTime"); + + mockModelUpdater.enterTestSuite("DemoTestCase1"); + mockModelUpdater.enterTestCase("DemoTest1"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("DemoTest2"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.enterTestSuite("DemoTestCase2"); + mockModelUpdater.enterTestCase("DemoTest1"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("DemoTest2"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 4 tests from 1 test case. + //[----------] Global test environment set-up. + //[----------] 4 tests from DemoTestCase + //[ RUN ] DemoTestCase.TestPass + //[ OK ] DemoTestCase.TestPass (0 ms) + //[ RUN ] DemoTestCase.TestFail + //demo_file.cc:38: Failure + //Value of: 2 + //Expected: 1 + //[ FAILED ] DemoTestCase.TestFail (0 ms) + //[ RUN ] DemoTestCase.TestAFewFails + //demo_file.cc:42: Failure + //Value of: 2 + //Expected: 1 + //demo_file.cc:43: Failure + //Value of: 2 + //Expected: 1 + //[ FAILED ] DemoTestCase.TestAFewFails (0 ms) + //[ RUN ] DemoTestCase.TestCustomFails + //demo_file.cc:47: Failure + //Failed + //Custom fatal fail! + //demo_file.cc:48: Failure + //Failed + //Another custom fatal fail! + //demo_file.cc:49: Failure + //Failed + //Yet another custom fatal fail! + //[ FAILED ] DemoTestCase.TestCustomFails (0 ms) + //[----------] 4 tests from DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 4 tests from 1 test case ran. (1 ms total) + //[ PASSED ] 1 test. + //[ FAILED ] 3 tests, listed below: + //[ FAILED ] DemoTestCase.TestFail + //[ FAILED ] DemoTestCase.TestAFewFails + //[ FAILED ] DemoTestCase.TestCustomFails + // + // 3 FAILED TESTS + public void testDifferentTestStatuses() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("exitTestSuite"); + mockModelUpdater.skipCalls("setTestingTime"); + + mockModelUpdater.enterTestCase("TestPass"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("TestFail"); + mockModelUpdater.addTestMessage("demo_file.cc", 38, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("TestAFewFails"); + mockModelUpdater.addTestMessage("demo_file.cc", 42, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1"); + mockModelUpdater.addTestMessage("demo_file.cc", 43, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("TestCustomFails"); + mockModelUpdater.addTestMessage("demo_file.cc", 47, ITestMessage.Level.Error, "Failed"+EOL+"Custom fatal fail!"); + mockModelUpdater.addTestMessage("demo_file.cc", 48, ITestMessage.Level.Error, "Failed"+EOL+"Another custom fatal fail!"); + mockModelUpdater.addTestMessage("demo_file.cc", 49, ITestMessage.Level.Error, "Failed"+EOL+"Yet another custom fatal fail!"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 2 tests from 1 test case. + //[----------] Global test environment set-up. + //[----------] 2 tests from DemoTestCase + //[ RUN ] DemoTestCase.TestWithSimpleTrace + //demo_file.cc:36: Failure + //Value of: 2 + //Expected: 1 + //Google Test trace: + //demo_file.cc:41: Trace point #2 in TestWithSimpleTrace + //demo_file.cc:40: Trace point #1 in TestWithSimpleTrace + //[ FAILED ] DemoTestCase.TestWithSimpleTrace (1 ms) + //[ RUN ] DemoTestCase.TestTraceForMultipleFails + //demo_file.cc:36: Failure + //Value of: 2 + //Expected: 1 + //Google Test trace: + //demo_file.cc:46: Trace point #1 in TestTraceForMultipleFails + //demo_file.cc:36: Failure + //Value of: 2 + //Expected: 1 + //Google Test trace: + //demo_file.cc:48: Trace point #2 in TestTraceForMultipleFails + //demo_file.cc:46: Trace point #1 in TestTraceForMultipleFails + //[ FAILED ] DemoTestCase.TestTraceForMultipleFails (0 ms) + //[----------] 2 tests from DemoTestCase (1 ms total) + // + //[----------] Global test environment tear-down + //[==========] 2 tests from 1 test case ran. (1 ms total) + //[ PASSED ] 0 tests. + //[ FAILED ] 2 tests, listed below: + //[ FAILED ] DemoTestCase.TestWithSimpleTrace + //[ FAILED ] DemoTestCase.TestTraceForMultipleFails + // + // 2 FAILED TESTS + public void testScopedTraceSupport() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("exitTestSuite"); + mockModelUpdater.skipCalls("setTestingTime"); + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestCase("TestWithSimpleTrace"); + mockModelUpdater.addTestMessage("demo_file.cc", 36, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1"); + mockModelUpdater.addTestMessage("demo_file.cc", 41, ITestMessage.Level.Info, "Trace point #2 in TestWithSimpleTrace"); + mockModelUpdater.addTestMessage("demo_file.cc", 40, ITestMessage.Level.Info, "Trace point #1 in TestWithSimpleTrace"); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("TestTraceForMultipleFails"); + mockModelUpdater.addTestMessage("demo_file.cc", 36, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1"); + mockModelUpdater.addTestMessage("demo_file.cc", 46, ITestMessage.Level.Info, "Trace point #1 in TestTraceForMultipleFails"); + mockModelUpdater.addTestMessage("demo_file.cc", 36, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1"); + mockModelUpdater.addTestMessage("demo_file.cc", 48, ITestMessage.Level.Info, "Trace point #2 in TestTraceForMultipleFails"); + mockModelUpdater.addTestMessage("demo_file.cc", 46, ITestMessage.Level.Info, "Trace point #1 in TestTraceForMultipleFails"); + mockModelUpdater.exitTestCase(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.TestMessageLocationFormats + //demo_file_name2.cpp:40: Failure + //Standard format with file name & line number + //unknown file:41: Failure + //Standard format with unknown file name + //demo_file_name2.cpp(42): Failure + //VS-like format with file name & line number + //unknown file(43): Failure + //VS-like format with unknown file name + //demo_file_name2.cpp: Failure + //Location with unknown line number + //unknown file: Failure + //Location with unknown file name & line number + //[ FAILED ] DemoTestCase.TestMessageLocationFormats (1 ms) + //[----------] 1 test from DemoTestCase (1 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (1 ms total) + //[ PASSED ] 0 tests. + //[ FAILED ] 1 test, listed below: + //[ FAILED ] DemoTestCase.TestMessageLocationFormats + // + // 1 FAILED TEST + public void testDifferentLocationsFormatsWithStandardMessageFormat() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("exitTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + mockModelUpdater.skipCalls("exitTestCase"); + mockModelUpdater.skipCalls("setTestingTime"); + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.addTestMessage("demo_file_name2.cpp", 40, ITestMessage.Level.Error, "Standard format with file name & line number"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 41, ITestMessage.Level.Error, "Standard format with unknown file name"); + mockModelUpdater.addTestMessage("demo_file_name2.cpp", 42, ITestMessage.Level.Error, "VS-like format with file name & line number"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 43, ITestMessage.Level.Error, "VS-like format with unknown file name"); + mockModelUpdater.addTestMessage("demo_file_name2.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown line number"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown file name & line number"); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.TestMessageLocationFormats + //demo_file_name2.cpp:40: error: Standard format with file name & line number + //unknown file:41: error: Standard format with unknown file name + //demo_file_name2.cpp(42): error: VS-like format with file name & line number + //unknown file(43): error: VS-like format with unknown file name + //demo_file_name2.cpp: error: Location with unknown line number + //unknown file: error: Location with unknown file name & line number + //[ FAILED ] DemoTestCase.TestMessageLocationFormats (1 ms) + //[----------] 1 test from DemoTestCase (1 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (1 ms total) + //[ PASSED ] 0 tests. + //[ FAILED ] 1 test, listed below: + //[ FAILED ] DemoTestCase.TestMessageLocationFormats + // + // 1 FAILED TEST + public void testDifferentLocationsFormatsWithVSLikeMessageFormat() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("exitTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + mockModelUpdater.skipCalls("exitTestCase"); + mockModelUpdater.skipCalls("setTestingTime"); + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.addTestMessage("demo_file_name2.cpp", 40, ITestMessage.Level.Error, "Standard format with file name & line number"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 41, ITestMessage.Level.Error, "Standard format with unknown file name"); + mockModelUpdater.addTestMessage("demo_file_name2.cpp", 42, ITestMessage.Level.Error, "VS-like format with file name & line number"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 43, ITestMessage.Level.Error, "VS-like format with unknown file name"); + mockModelUpdater.addTestMessage("demo_file_name2.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown line number"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown file name & line number"); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.TestMultiLineMessage + //demo_file.cc:40: Failure + //Line 1 + //Line 2 + //Line 3 + //[ FAILED ] DemoTestCase.TestMultiLineMessage (0 ms) + //[----------] 1 test from DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 0 tests. + //[ FAILED ] 1 test, listed below: + //[ FAILED ] DemoTestCase.TestMultiLineMessage + // + // 1 FAILED TEST + public void testMultiLineMessage() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("exitTestSuite"); + mockModelUpdater.skipCalls("setTestingTime"); + mockModelUpdater.skipCalls("setTestStatus"); + + mockModelUpdater.enterTestCase("TestMultiLineMessage"); + mockModelUpdater.addTestMessage("demo_file.cc", 40, ITestMessage.Level.Error, "Line 1"+EOL+"Line 2"+EOL+"Line 3"); + mockModelUpdater.exitTestCase(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 2 tests from 2 test cases. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase1 + //[ RUN ] DemoTestCase1.Test1 + //unknown file: Failure + //Unknown C++ exception thrown in the test body. + //[ FAILED ] DemoTestCase1.Test1 (1000 ms) + //[----------] 1 test from DemoTestCase1 (1000 ms total) + // + //[----------] 1 test from DemoTestCase2 + //[ RUN ] DemoTestCase2.Test2 + //[ OK ] DemoTestCase2.Test2 (2000 ms) + //[----------] 1 test from DemoTestCase2 (2000 ms total) + // + //[----------] Global test environment tear-down + //[==========] 2 tests from 2 test cases ran. (3000 ms total) + //[ PASSED ] 1 test. + //[ FAILED ] 1 test, listed below: + //[ FAILED ] DemoTestCase1.Test1 + // + // 1 FAILED TEST + public void testTestingTimeSupport() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("exitTestSuite"); + mockModelUpdater.skipCalls("setTestStatus"); + mockModelUpdater.skipCalls("addTestMessage"); + + mockModelUpdater.enterTestCase("Test1"); + mockModelUpdater.setTestingTime(1000); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("Test2"); + mockModelUpdater.setTestingTime(2000); + mockModelUpdater.exitTestCase(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 3 tests from 1 test case. + //[----------] Global test environment set-up. + //[----------] 3 tests from Inst/DemoTestCase + //[ RUN ] Inst/DemoTestCase.Test/0 + //demo_file.cc:50: Failure + //Failed + //Param1 + //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = "Param1" (0 ms) + //[ RUN ] Inst/DemoTestCase.Test/1 + //[ OK ] Inst/DemoTestCase.Test/1 (0 ms) + //[ RUN ] Inst/DemoTestCase.Test/2 + //demo_file.cc:50: Failure + //Failed + //Param3 + //[ FAILED ] Inst/DemoTestCase.Test/2, where GetParam() = "Param3" (0 ms) + //[----------] 3 tests from Inst/DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 3 tests from 1 test case ran. (0 ms total) + //[ PASSED ] 1 test. + //[ FAILED ] 2 tests, listed below: + //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = "Param1" + //[ FAILED ] Inst/DemoTestCase.Test/2, where GetParam() = "Param3" + // + // 2 FAILED TESTS + public void testParametrizedTestsSupport() { + mockModelUpdater.enterTestSuite("Inst/DemoTestCase"); + mockModelUpdater.enterTestCase("Test/0"); + mockModelUpdater.addTestMessage("demo_file.cc", 50, ITestMessage.Level.Error, "Failed"+EOL+"Param1"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info, "Instantiated with GetParam() = \"Param1\""); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("Test/1"); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("Test/2"); + mockModelUpdater.addTestMessage("demo_file.cc", 50, ITestMessage.Level.Error, "Failed"+EOL+"Param3"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info, "Instantiated with GetParam() = \"Param3\""); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from Inst/DemoTestCase + //[ RUN ] Inst/DemoTestCase.Test/0 + //demo_file.cc:50: Failure + //Failed + //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = 0x4f50cc (0 ms) + //[----------] 1 test from Inst/DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 0 tests. + //[ FAILED ] 1 test, listed below: + //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = 0x4f50cc + // + // 2 FAILED TESTS + public void testParametrizedTestsWithoutQuotesSupport() { + mockModelUpdater.enterTestSuite("Inst/DemoTestCase"); + mockModelUpdater.enterTestCase("Test/0"); + mockModelUpdater.addTestMessage("demo_file.cc", 50, ITestMessage.Level.Error, "Failed"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info, "Instantiated with GetParam() = 0x4f50cc"); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 3 tests from 3 test cases. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase/0, where TypeParam = char + //[ RUN ] DemoTestCase/0.Test + //demo_file.cc:60: Failure + //Failed + //char type + //[ FAILED ] DemoTestCase/0.Test, where TypeParam = char (0 ms) + //[----------] 1 test from DemoTestCase/0 (0 ms total) + // + //[----------] 1 test from DemoTestCase/1, where TypeParam = int + //[ RUN ] DemoTestCase/1.Test + //[ OK ] DemoTestCase/1.Test (0 ms) + //[----------] 1 test from DemoTestCase/1 (0 ms total) + // + //[----------] 1 test from DemoTestCase/2, where TypeParam = unsigned int + //[ RUN ] DemoTestCase/2.Test + //demo_file.cc:60: Failure + //Failed + //unsigned int type + //[ FAILED ] DemoTestCase/2.Test, where TypeParam = unsigned int (0 ms) + //[----------] 1 test from DemoTestCase/2 (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 3 tests from 3 test cases ran. (0 ms total) + //[ PASSED ] 1 test. + //[ FAILED ] 2 tests, listed below: + //[ FAILED ] DemoTestCase/0.Test, where TypeParam = char + //[ FAILED ] DemoTestCase/2.Test, where TypeParam = unsigned int + // + // 2 FAILED TESTS + public void testTypedTestsSupport() { + mockModelUpdater.enterTestSuite("DemoTestCase/0(char)"); + mockModelUpdater.enterTestCase("Test"); + mockModelUpdater.addTestMessage("demo_file.cc", 60, ITestMessage.Level.Error, "Failed"+EOL+"char type"); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.enterTestSuite("DemoTestCase/1(int)"); + mockModelUpdater.enterTestCase("Test"); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + mockModelUpdater.enterTestSuite("DemoTestCase/2(unsigned int)"); + mockModelUpdater.enterTestCase("Test"); + mockModelUpdater.addTestMessage("demo_file.cc", 60, ITestMessage.Level.Error, "Failed"+EOL+"unsigned int type"); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + //Running main() from gtest_main.cc + //Unknown line in the output + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //Another unknown line in the output + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.DemoTest + //Yet another unknown line in the output + //[ OK ] DemoTestCase.DemoTest (0 ms) + //[----------] 1 test from DemoTestCase (0 ms total) + //One more unknown line in the output + // + //[----------] Global test environment tear-down + //And one more unknown line in the output + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 1 test. + public void testAllUnrecognizedLinesShouldBeSkipped() { + mockModelUpdater.enterTestSuite("DemoTestCase"); + mockModelUpdater.enterTestCase("DemoTest"); + mockModelUpdater.setTestingTime(0); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + public void testNoInput() { + // NOTE: The comment above is left blank intentionally + expectTestingException(); + } + + + // This is not an input from a Google Test Module + public void testAbsolutelyIncorrectInput() { + expectTestingException(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] Not_A_DemoTestCase.DemoTest + public void testUnexpectedOutputEnd() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + + expectTestingException(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] Not_A_DemoTestCase.DemoTest + //[ OK ] DemoTestCase.DemoTest (0 ms) + //[----------] 1 test from DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 1 test. + public void testTestSuiteNameMismatch1() { + mockModelUpdater.skipCalls("enterTestSuite"); + + expectTestingException(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.DemoTest + //[ OK ] Not_A_DemoTestCase.DemoTest (0 ms) + //[----------] 1 test from DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 1 test. + public void testTestSuiteNameMismatch2() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + + expectTestingException(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.DemoTest + //[ OK ] DemoTestCase.DemoTest (0 ms) + //[----------] 1 test from Not_A_DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 1 test. + public void testTestSuiteNameMismatch3() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + mockModelUpdater.skipCalls("setTestingTime"); + mockModelUpdater.skipCalls("setTestStatus"); + mockModelUpdater.skipCalls("exitTestCase"); + + expectTestingException(); + } + + + //Running main() from gtest_main.cc + //[==========] Running 1 test from 1 test case. + //[----------] Global test environment set-up. + //[----------] 1 test from DemoTestCase + //[ RUN ] DemoTestCase.DemoTest + //[ OK ] DemoTestCase.NOT_A_DemoTest (0 ms) + //[----------] 1 test from DemoTestCase (0 ms total) + // + //[----------] Global test environment tear-down + //[==========] 1 test from 1 test case ran. (0 ms total) + //[ PASSED ] 1 test. + public void testTestCaseNameMismatch() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + + expectTestingException(); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java new file mode 100644 index 00000000000..218284173d5 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java @@ -0,0 +1,221 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.testsrunners; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; + +import junit.framework.Assert; + +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestCase; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestItem.Status; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.eclipse.cdt.testsrunner.model.ITestMessage.Level; +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.ITestSuite; + +/** + * Mock for the {@see ITestModelUpdater}. + */ +@SuppressWarnings("nls") +public class MockTestModelUpdater implements ITestModelUpdater { + + private class FakeTestItem implements ITestItem { + + private String name = null; + + protected void unexpectedMethodCall() { + Assert.fail("Unexpected method call"); + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void resetName() { + name = null; + } + + // Unimplemented methods + @Override + public Status getStatus() { unexpectedMethodCall(); return null; } + @Override + public int getTestingTime() { unexpectedMethodCall(); return 0; } + @Override + public ITestSuite getParent() { unexpectedMethodCall(); return null; } + @Override + public boolean hasChildren() { unexpectedMethodCall(); return false; } + @Override + public ITestItem[] getChildren() { unexpectedMethodCall(); return null; } + @Override + public void visit(IModelVisitor visitor) { unexpectedMethodCall(); } + } + + private class FakeTestCase extends FakeTestItem implements ITestCase { + @Override + public ITestMessage[] getTestMessages() { unexpectedMethodCall(); return null; } + } + + private class FakeTestSuite extends FakeTestItem implements ITestSuite { + } + + + private class MethodInfo { + + private String methodName; + private Object[] args; + + MethodInfo(String methodName, Object[] args) { + this.methodName = methodName; + this.args = args; + } + + private String genArgs(String methodName, Object[] args) { + StringBuilder sb = new StringBuilder(); + sb.append(methodName); + sb.append("("); + boolean needDelimited = false; + for (Object arg : args) { + if (needDelimited) { + sb.append(", "); + } else { + needDelimited = true; + } + if (arg != null) { + sb.append('"'); + sb.append(arg.toString()); + sb.append('"'); + } else { + sb.append("null"); + } + } + sb.append(")"); + return sb.toString(); + } + + public void check(String methodName, Object[] args) { + if (!this.methodName.equals(methodName)) { + Assert.failNotEquals("Unexpected method call. ", + genArgs(this.methodName, this.args), genArgs(methodName, args)); + } + boolean compareFailed = (this.args.length != args.length); + if (!compareFailed) { + for (int i = 0; i < args.length; i++) { + if (this.args[i] == null) { + if (args[i] != null) { + compareFailed = true; + break; + } + } else if (!this.args[i].equals(args[i])) { + compareFailed = true; + break; + } + } + } + if (compareFailed) { + Assert.failNotEquals("Unexpected parameters of method "+this.methodName+"(). ", + genArgs(this.methodName, this.args), genArgs(methodName, args)); + } + } + } + + + private LinkedList methodCalls = new LinkedList(); + private boolean replayMode = false; + private Set skippedMethods = new HashSet(); + + // NOTE: Test suites nesting is not supported yet cause there is no need in it + private FakeTestSuite currentTestSuite = new FakeTestSuite(); + private FakeTestCase currentTestCase = new FakeTestCase(); + + + @Override + public void enterTestSuite(String name) { + genericImpl("enterTestSuite", name); + // NOTE: Test suites or cases nesting is not supported for mocking + currentTestSuite.setName(name); + } + + @Override + public void exitTestSuite() { + genericImpl("exitTestSuite"); + currentTestSuite.resetName(); + } + + @Override + public void enterTestCase(String name) { + genericImpl("enterTestCase", name); + currentTestCase.setName(name); + } + + + @Override + public void setTestStatus(Status status) { + genericImpl("setTestStatus", status); + } + + @Override + public void setTestingTime(int testingTime) { + genericImpl("setTestingTime", testingTime); + } + + @Override + public void exitTestCase() { + genericImpl("exitTestCase"); + currentTestCase.resetName(); + } + + @Override + public void addTestMessage(String file, int line, Level level, String text) { + genericImpl("addTestMessage", file, line, level, text); + } + + @Override + public ITestSuite currentTestSuite() { + return currentTestSuite; + } + + @Override + public ITestCase currentTestCase() { + return currentTestCase; + } + + public void skipCalls(String methodName) { + skippedMethods.add(methodName); + } + + public void replay() { + replayMode = true; + } + + private void genericImpl(String methodName, Object... args) { + if (!skippedMethods.contains(methodName)) { + if (replayMode) { + if (methodCalls.isEmpty()) { + Assert.fail("Unexpected method call "+methodName+"()"); + } else { + methodCalls.pollFirst().check(methodName, args); + } + } else { + methodCalls.addLast(new MethodInfo(methodName, args)); + } + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java new file mode 100644 index 00000000000..b5dc9dc8f51 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java @@ -0,0 +1,693 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.testsrunners; + +import java.text.MessageFormat; + +import org.eclipse.cdt.testsrunner.internal.qttest.QtTestsRunnerProvider; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestMessage; + + +/** + * Test for {@see QtTestsRunner} class + */ +@SuppressWarnings("nls") +public class QtTestCase extends BaseTestCase { + + private static final String DEFAULT_LOCATION_FILE = ""; + private static final int DEFAULT_LOCATION_LINE = 0; + + @Override + protected ITestsRunnerProvider createTestsRunner() { + return new QtTestsRunnerProvider(); + } + + + private void addStandardBenchmarkMessage(int value, String units, int iterations) { + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info, + MessageFormat.format("{0,number,#.####} {1} per iteration (total: {2}, iterations: {3})", + ((float)value)/iterations, units, value, iterations) + ); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + public void testNoCustomTestCases() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + public void testTheOnlyPassingCustomTestCase() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testTheOnlyFailingCustomTestCase() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 6, ITestMessage.Level.FatalError, + "Compared values are not the same\n Actual (1): 1\n Expected (2): 2"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + public void testTheOnlyAbortedCustomTestCase() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo"); + mockModelUpdater.addTestMessage("qtestcase.cpp", 1675, ITestMessage.Level.FatalError, + "Caught unhandled exception"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + // NOTE: Qt.Test does not run any other test cases after exception throwing in a test case + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testDifferentMessageLevels() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testWarning"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, "Test warning!"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testFailure"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 41, ITestMessage.Level.FatalError, "Test fail!"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testSkip"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 47, ITestMessage.Level.Info, "Test skip!"); + mockModelUpdater.setTestStatus(ITestItem.Status.Skipped); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testExpectedFailWithContinue"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 60, ITestMessage.Level.Error, "Will fix in the next release"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 61, ITestMessage.Level.FatalError, "Failed!"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testExpectedFailWithAbort"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 68, ITestMessage.Level.Error, "Will fix in the next release"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testExpectedFailPassed"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 70, ITestMessage.Level.Error, "COMPARE()"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testUnknownIncidentType"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 72, ITestMessage.Level.FatalError, "Unknown incident test!"); + mockModelUpdater.setTestStatus(ITestItem.Status.Aborted); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testUnknownMessageType"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 80, ITestMessage.Level.FatalError, "Unknown message type test!"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + public void testBenchmarkBasicSupport() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo"); + addStandardBenchmarkMessage(28, "msec", 8192); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testBenchmarkWithDataTag() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(locale aware compare)"); + addStandardBenchmarkMessage(30, "instr.", 8192); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(standard compare)"); + addStandardBenchmarkMessage(24, "instr.", 10485); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testBenchmarkMixedWithIncidentsWithDataTag() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(locale aware compare)"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 57, ITestMessage.Level.FatalError, "Failed!"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 57, ITestMessage.Level.FatalError, "Failed!"); + addStandardBenchmarkMessage(29, "ticks", 8192); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(standard compare)"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 58, ITestMessage.Level.FatalError, "Failed!"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 58, ITestMessage.Level.FatalError, "Failed!"); + addStandardBenchmarkMessage(24, "ticks", 10485); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testIncidentWithDataTag() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(all lower)"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 20, ITestMessage.Level.FatalError, + "Compared values are not the same\n Actual (string.toUpper()): HELLO\n Expected (result): HELLO2"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(mixed)"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 20, ITestMessage.Level.FatalError, + "Compared values are not the same\n Actual (string.toUpper()): HELLO\n Expected (result): HELLO3"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testMessageWithDataTag() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(all lower)"); + mockModelUpdater.addTestMessage("", 0, ITestMessage.Level.Warning, "hello"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 66, ITestMessage.Level.FatalError, "HELLO2"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testDemo(mixed)"); + mockModelUpdater.addTestMessage("", 0, ITestMessage.Level.Warning, "Hello"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 66, ITestMessage.Level.FatalError, "HELLO3"); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + public void testWithEmptyMessage() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testWithEmptyIncident"); + mockModelUpdater.addTestMessage("qt_test_demo.cpp", 6, ITestMessage.Level.FatalError, ""); + mockModelUpdater.setTestStatus(ITestItem.Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testWithEmptyMessage"); + mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, ""); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + // + // + // + public void testWithoutAnyIncidents() { + mockModelUpdater.enterTestSuite("MainTS"); + mockModelUpdater.enterTestCase("initTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("testWithoutAnyIncidents"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("cleanupTestCase"); + mockModelUpdater.setTestStatus(ITestItem.Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.exitTestSuite(); + } + + + // + public void testNoInput() { + // NOTE: The comment above is left blank intentionally + expectTestingException(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + public void testBadFormedXml() { + mockModelUpdater.skipCalls("enterTestSuite"); + expectTestingException(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + public void testUnexceptedXmlEnd() { + mockModelUpdater.skipCalls("enterTestSuite"); + expectTestingException(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + public void testBadIncidentTypeValue() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + public void testBadMessageTypeValue() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + public void testBadLineNumberValueOfIncident() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + // + // + public void testBadLineNumberValueOfMessage() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + + // + // + // + // 4.6.2 + // 4.6.2 + // + // + // + // + // + public void testBadBenchmarkMetricValue() { + mockModelUpdater.skipCalls("enterTestSuite"); + mockModelUpdater.skipCalls("enterTestCase"); + expectTestingException(); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/test.xml b/testsrunner/org.eclipse.cdt.testsrunner.test/test.xml new file mode 100644 index 00000000000..eed63892c11 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/test.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/.classpath b/testsrunner/org.eclipse.cdt.testsrunner/.classpath new file mode 100644 index 00000000000..deb673668e9 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/.project b/testsrunner/org.eclipse.cdt.testsrunner/.project new file mode 100644 index 00000000000..e4270dc3e92 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/.project @@ -0,0 +1,34 @@ + + + org.eclipse.cdt.testsrunner + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0e860bfc279 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,82 @@ +#Mon Apr 16 13:01:24 EEST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..b7d79fc37d0 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF @@ -0,0 +1,37 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.cdt.testsrunner;singleton:=true +Bundle-Version: 7.0.0.qualifier +Bundle-Activator: org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime;bundle-version="3.5.0", + org.eclipse.cdt.core;bundle-version="5.1.0", + org.eclipse.core.resources;bundle-version="3.5.0", + org.eclipse.debug.ui;bundle-version="3.5.0", + org.eclipse.cdt.debug.core;bundle-version="6.0.0", + org.eclipse.cdt.debug.ui, + org.eclipse.cdt.ui, + org.eclipse.cdt.dsf.gdb.ui, + org.eclipse.cdt.dsf.gdb +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Import-Package: org.eclipse.cdt.dsf.gdb.launching, + org.eclipse.cdt.internal.ui.viewsupport, + org.eclipse.cdt.launch, + org.eclipse.cdt.launch.internal.ui, + org.eclipse.cdt.launch.ui, + org.eclipse.core.filesystem, + org.eclipse.jface.text, + org.eclipse.ui.ide, + org.eclipse.ui.texteditor +Export-Package: org.eclipse.cdt.testsrunner.internal, + org.eclipse.cdt.testsrunner.internal.launcher, + org.eclipse.cdt.testsrunner.internal.model, + org.eclipse.cdt.testsrunner.internal.ui.launcher, + org.eclipse.cdt.testsrunner.internal.ui.view, + org.eclipse.cdt.testsrunner.internal.ui.view.actions, + org.eclipse.cdt.testsrunner.launcher, + org.eclipse.cdt.testsrunner.model diff --git a/testsrunner/org.eclipse.cdt.testsrunner/about.html b/testsrunner/org.eclipse.cdt.testsrunner/about.html new file mode 100644 index 00000000000..d7c511887d6 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/about.html @@ -0,0 +1,24 @@ + + +About + + +

About This Content

+ +

June 22, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner/build.properties b/testsrunner/org.eclipse.cdt.testsrunner/build.properties new file mode 100644 index 00000000000..bc8bffa7696 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/build.properties @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### + +bin.includes = plugin.xml,\ + plugin.properties,\ + icons/,\ + about.html,\ + .,\ + META-INF/ +javadoc.packages = org.eclipse.cdt.launch.ui.*,\ + org.eclipse.cdt.launch.sourcelookup*,\ + org.eclipse.cdt.launch.* +source.. = src/ +src.includes = about.html,\ + schema/ diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/history_list.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/history_list.gif new file mode 100644 index 0000000000000000000000000000000000000000..131063ce97dc3d8dd80eb9c4c4611e817a2dbed0 GIT binary patch literal 225 zcmZ?wbhEHb6krfwIKsg2|NsA2uUC_h+DP*n!_m+kIl|TlTw@u$Sq&L1%1orsNmT2^ z_DiT#9(J6yH@+aEXW5*sS|(zZ+msABOEo)vH#sN@8WgTC{CY)tdVmf?ZkaB7Riz;# M6APQ6p(2Ad0Gg&?q5uE@ literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_auto.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_auto.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b93aaca769bc97f4a61782e987e62c4265b3220 GIT binary patch literal 338 zcmZ?wbhEHb6krfwxXQq=YtO+W$4>3uv+v#ek2i1K*}QG{{)0y@UAw(}{r0VU4)55t z=hyE)KY#uH@$=W$?>|0#`TFzs@4x^4{rUU%_n$wf&zw1Y7%Dk9zDB%@2&Ia4({E1^w6P02M_-L|DS<2K=CIFBLjmHgAT}eke?XX@*O4? zc<4xVE?i<%BGM)opt1R`aw*Y6)ce;qz@ z^uw30KY#!J@$1*0zkh%K`E&Tlky97W&0Dqj%FS#0j_x~g;>d{;M~@#rdhFQIQzws{ zI(hWui6dwC@4a>Y-2JOp4jnvr?AWpY|Nk@43@H9&VPs%XWY7WG0P+(9Tm69v1s*zl z_9vDYRmND%ow@w;=G?SrE7AK%h$DkF000h%4gdfE literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_vertical.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_vertical.gif new file mode 100644 index 0000000000000000000000000000000000000000..5bffca21bc82a43b2b3db45566740769a12df9c3 GIT binary patch literal 219 zcmZ?wbhEHb6krfwIKsfNYtO+W$4=e6b!YRo-RCY`{`u?okDtFjeEItG_wPS{|Nj2- zXWpvCS8iV0cXZ#eV@J>K-+Sx)x%*eI96EUL|Ns9CL;%H~EQ|~c!VEefwIDkgSR)>& z^rcvOWvp8E{NcV2id)YdlBmc#v#3O;w>6Q0Lx9D47H^}5!OT6K{*G&-7Vm2*JAKq@ s--8Xz(%O?tU!=TeXtcSMrD^@iL7$feVJBl6IU}@NjTITJ0dnSFJ^%m! literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/rerun.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/rerun.gif new file mode 100644 index 0000000000000000000000000000000000000000..bfadfaa089a79ce9f027fdab43439f702f6d2253 GIT binary patch literal 580 zcmZ?wbhEHb6krfwc*ekRWa)`B`_CO)dFIIB6Ne5RJ88`o}Kw|euM$#bX7 zTQPs`@_92B&0Ml>>FlMm*KJw1Ve5v?+c$68w(0uq>sN1Hz4!3m?R&Rx-Mw}7#?>{O zSFhZ#V(FSCGw09PvU~HkJzM84oxO3#`t{q^ZrZV7_rV=E?p%BH;Si$|8sn{?F2I@h1x-14A%_4#+K_IALI4 z*bp4d5)jxHz|_>$#U^j>U~8eP$k5%y%x`RBXKiV2ti(7iK+`}q$l1!w$jD_{pq93J z&hW$3O`+# PWZ5NVJTF*;gTWdAdqTUVSreem&vYxnP5+P7=n)JdIBAKkon`_l6# zcb+}Ief9F$^JkC0d-Lq&^M~8FZC<}>?%EY|)-0dBdfBX%OJ?lYvg+geSMT4xSigGF zotu|VpEz{w%7uG(ZoC4jesJ&er;mpY9{m6R|G$6#{{H<7WH1ahp!k!8k%7U5K?me; zP@FKZuWWE>YHn$5cIfEr>S}Tj@1M{wJ;9+@Tx`ZnF@14fmZ>g%vt~+(Gczyf6J5PV zlz%<{N{QvmMYeIU3JI;$QB<^MViFeS<~+7i)!trJn~{;3hwIW*2L&5PM>_>uMkYb= z)mKb(tgLiQtRxu)-UwV#mXX(!)iQ9FWS_Fo%-q6MS2Kx2^3j6J%LC+!W*AI#Zsk#Q d;)!8kXprg>R&tr6V3;hpC_v6pl#7MI8US7A;iv!r literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_next.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_next.gif new file mode 100644 index 0000000000000000000000000000000000000000..388ef91e0c0ec3af940118dde09da4c58713c4e0 GIT binary patch literal 204 zcmZ?wbhEHb6krfwIKsg2^XIo;zkdAu`TfKDSFc_?`11MvlZV$I+`0Jd@$I*-pML-L z`P;K|=oc3Res=YheEpBXdG`&~(_ R_2`$&HV>0iZe?Jw1_1voPqY94 literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_previous.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_previous.gif new file mode 100644 index 0000000000000000000000000000000000000000..c00fe058dac5fdc313c731b411d3587ae23ed49b GIT binary patch literal 152 zcmV;J0B8S4Nk%w1VGsZi0J8u9`1tku`uOke==AgNv8|u$>Ei0>;o{%b;M~#XF@36>*(S5_w~ZT!T1X%C!W$PaVeN=WQu5p? nyK3LFm$Sm{s?Fq%^@ysX8YyoAn_OxP1- v^X5-MJ9|R`hs6UiuI7Z3A`*RF3V|6ssvI|T9=2;$E}Y+=<`d__z+epkhGsnf literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/history_list.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/history_list.gif new file mode 100644 index 0000000000000000000000000000000000000000..364c0e70b1d6dc48f9d9abfceafbb4f63e5e1edb GIT binary patch literal 586 zcmZ?wbhEHb6krfwc*el6W%tD&KmUCB_Pefs%iNVm(`#3L`uh9Zk3TTdfM8Hb2nXEy7Tt)cRyde`|-ygpG`u5}Z!`D9^y!!t5&5tK+PqXU%vnDpS5D*?Bx$%1I52TfB*C4 zho3Lr|9Jo9*Qam4r_5RU^xco=?|;1d`19kp-=Dty`uOeF_g{Zz%wJ?aBVon4?KL}U z=PjDIXzA<~E2ghqJ!Rv%iCZ`H?cLhBb5qa$Z5{vr|7RG2K=CIFBLjmogAT~;pg3V* zU*6#C?9|fQ*3#7Ez|qs&=g{fw$YEh_(bwZR(Vo%V(wvc%nT5gBexjZ1R0~=5wQKDr z+A^tZW!kbu#de~N$!c9=Ha2M^n~Byk^UQS?E#bAEXeGK@^s17wsMSO>DMP8dckgML zP1Ms|ZJ^B~EF!5lQC0tx{#gcn)rnjRs}(d96cimaI$9DN+l4u7Z3-qFXzuiIHmI5L XgV9NeM?!&bXM&>>OK%esBZD;nX%XK6 literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_auto.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_auto.gif new file mode 100644 index 0000000000000000000000000000000000000000..45469ad67c4066af8a77b8d0a10d7343e4a58171 GIT binary patch literal 358 zcmZ?wbhEHb6krfwxXQq=W%tF-8N1VKSC({aXq&RGW9pio>8q|k{?b2dMR@OtS-bDo zbkAv?FmKA7rIwX@uRVG_ecqz?zy4qS{Qupr|1;(<`uO|**FXP%{Qdvv`~Nq;{(t!W z|I45MuYdi2|NH;vKmWh~{l9$G>aTzQ|N8ged`7~GbK7fn)XrNpZ_(1(i5c0qZr#v#^4O-mTRV4d>e;cWcmKAI;M1%8L$Dx zpDc_F3>FMJAW4v)7}%N}<`j77NOf*rQdA~#NF_jHO=q_!U*}p^R)dFKm{&lkP^@sHv;a4kBnQjRUAuR3^GULW@C$Xxu!ii}>BwLW0L<>J A3jhEB literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_horizontal.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_horizontal.gif new file mode 100644 index 0000000000000000000000000000000000000000..d590470446f37e7d83ccbcf3f3a85f82e4fc344b GIT binary patch literal 374 zcmZ?wbhEHb6krfwxXQrLHf3GM)HOZRS6zSnrGM6n@ZJ-%cHf^eXQ^f7-fw^YfBOCZ z>gWIOe*K>@f6>R^|G)nE|K`{Kx4-^>`2GLOpZ~9a{eSoS|NGznKmYmv{qO&`zyE&% z3Idh={XhBWCi58yE6#1N*-<-h(Y!@VXRlZ>eeLQg8`n+Tx}k6H*3O-qdiHPYcsFnI zgY3B16Wjj(|Ia`cQ2fcl$iSe>paaqk@)HBwT literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_vertical.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_vertical.gif new file mode 100644 index 0000000000000000000000000000000000000000..dee0cbca025e70a1b11297b49c9f32e4325f8cd3 GIT binary patch literal 352 zcmZ?wbhEHb6krfwxXQq=W%tF-8N27NKAv8?vZP}}+mv-3Q`huNU)4Wr#gsWq-~al5 z_4EH3^A~;n^Z&=+|6l(6fBozK```b~XC$mRx4mXZ?Yu?v7A>8WqPZmZ721N!PkPRR|F|gGhm{8!M!)JYB ziIL?Uop~2tBpE-^QJch>a=NvkZB}cGQX>xsBO}8i$+UGhJzNy0r?<^G`uO6F-`^#i z#ku)f+uFsQ#kzZXdz?jsCW$)paL3LN;Bn^UR#1?iDZuH>F;7ljFg=q&ki(gsTYhtW X9lJAIOZ#p%XV(1(4jxc+WUvMR=0bUJ literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/rerun.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/rerun.gif new file mode 100644 index 0000000000000000000000000000000000000000..afb6fa934ceffc160ae422c20ce8f590676a31a7 GIT binary patch literal 590 zcmZ?wbhEHb6krfwc*elsJUPx|O1x2vr}LC(&xx^{FYVE7aj~Bo*1mV@((@a9r^lCU zX>QojxA@%JeYcJtyL0;3t<%?^+_IVM=R7^saZ-@)wAh5@1!0qti#F6Z?&vMvSnt^D z=QkrNXhxh(uZP#+&~PsoCp16L2}*PGh) zySPm7v?{mTc4>!skF{BumB$Pps}5V2$!|p zj|Uwe9<2CrA>qf3iXS%`HZ)6as1aG1$3H8Be`Tr2e=uO622lLT!pOjo!Jq>&3=}5} z?5i6xGFTl=gbCH3$ME2?Tfi%hakig?w{&&|&GEFvoD>z+HiTikrabvXo!B%K2$NE$>d_rouLfByx#?%&}fyLWD1v0z5d?5PE7 zR`f5Qld)u0*3=25e?Oo8@@(7R_j~_-IP~|^@xPx={{4Jz+a#5*w>thj?Emv*)}Lqd z{ydxi=h=d%56*AwR@~CBd~lw{vQCTROI&x%bh)uN_rvwRn@8H8UYvU8{F;hr;pKHQ z>)Pa3H_IR0Pa$D!M)0=Ky*z@`A!~bBwKs})NlZBCiA&o%?WF#m~ z7}(D@q%}3Sv^Lvxbar($*&6px=(m|*(`0F^Jad+^ov|d3U6Ylu%F<;jM#i$5Moren z+8Z}%Gi}}4WMQJVTTOMJ0<*BNLX&x7KtQ~NgpQ6bAFrrxQ$kQmN>H4hp1PKpn21tZ zl3PS-YO)+gMdQHc12(!2 M&1HruY61+_0K&N{n*aa+ literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_next.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_next.gif new file mode 100644 index 0000000000000000000000000000000000000000..072b1844572646fdb57124b6e938a465daac8d58 GIT binary patch literal 332 zcmZ?wbhEHb6krfwxXQrr@Ar$pzh3s)RRH2yZMG-dG{LyHRvkqv*C;prFW}Cb1QH0&9u|R~HDbFBMu_B(%Cf zXj8fH`cmQLIReYF1^)m4&p+|z+lLr1JVKV69Zf3ff)rJI#S8AmOS&g!objY zXp*F{?P9eo9}@`oK{Iw9&}i^SBU4D}c3FLN?5SiQ`V!5RSYo{04T literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_previous.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_previous.gif new file mode 100644 index 0000000000000000000000000000000000000000..07164754e5ca231666d9daf7fa4a9d12e378a52a GIT binary patch literal 323 zcmZ?wbhEHb6krfwxXQrr@9+D6zn=X4cJ<${r+>d*`SKk--`OT*-X9 literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_tests_hierarchy.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_tests_hierarchy.gif new file mode 100644 index 0000000000000000000000000000000000000000..234486172ca3778924ccb8815871b43a86908777 GIT binary patch literal 101 zcmZ?wbhEHb6krfwSj4~(Q?)9gZf#og#)(Uh=X7l^ny{;E%D(^q|117vVPs%nXV75) z0+3n;X03`{cm5ezIXq=zmO0EV=;)j|&1o9DrI+%u+JzZm7b91hTuEb(dA>qHg^|G; E05nA-vj6}9 literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/sort.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/sort.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d27529b6401cb8228cdcdc02394e5111a260487 GIT binary patch literal 157 zcmZ?wbhEHb6krfw*v!Dt=Qd?o<*NL$mekrQF|AAe`uB!(Z}yFfm2Rtco!n8ea?$_) z|C?pofyx-bK=CIFBLf3BgARxXGJ}D|tKg*P>R7IYOY&xVY>#a-jZ&SKlRkA_koR5= zHUE{HHgQ({ZQ)M#n8Ksia6st*g9nSa>SfIpVY-)3Iu;x-Q$6K+ohhMV?ta#Z5{wMi E09gV!rT_o{ literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/stop.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/stop.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc47edf06955eca15fee8118b3be43f019cae3f4 GIT binary patch literal 215 zcmZ?wbhEHb6krfwIKsg2!ocE%g~JO6j~5;RA2JFK2q?TzFgT%MaUr4LM1aGI2#+5d zR-ACK*kNJuA|T*HMa7R5D{jn~@&EsS2I7F?PZmZ71|bF=kaCcn46GpwRQggf=VfHM zdA;5hI8&!2R^8~yn?1}ARoqe>boi8dCIuYG;hM1Y7_-A#COOZb=7bkjye)1o4Ymf! gw+AT-W$b32*d*n&{`ylDm&EhWl|vdDg%laA0bm40+yDRo literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/eview16/cppunit.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/eview16/cppunit.gif new file mode 100644 index 0000000000000000000000000000000000000000..883170d6d3d6400f5b882eab3ce651028eec6ecc GIT binary patch literal 219 zcmZ?wbhEHb6krfwXc1$0uwm1~UAu2M`QP*ozZIW#JFECkNzI+Q*1H{jiY@+@{fRnV z;eoS@V;9zBEpIJb+t;^q!R-Ajmml4<`PA-mqX<;^V_ux zTN6D@HW-LKTsT2PrpMgbu`xhofwuFaE{_EFsCC=bmqzWEI=tzpig^3p9coMr)&R3} BIZyxq literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_aborted.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_aborted.gif new file mode 100644 index 0000000000000000000000000000000000000000..f866a2e1b2dd2b8e8cb77f26dae26027c15ee937 GIT binary patch literal 374 zcmZ?wbhEHb6krfwxXQqAQcU%py#9;a@)t!lZ+oWw`1$Ak=ii^d{rUOp&$G9`-hTS^ z^zF}=AAY_5`0L}>-_PIw`u6kBo!8IKKfax?t~P01UFych!tLF9?Y@?iB5nJlT&E`b z&d&;5k{`OLAZSi*z>KWuRTc4Ts$-UvMb0e9*wmc6rQLmQN_C0<{8{xow=SwH^=q&4 zX)gDjSnttO>ovF4b$XNAhJL#>Jr2veoECLB?_N=Mdf%Ka6Kwy30Rsk5{K>+|z+lOs z1CjyxiGgkMfjI`{+EV>T6$KCGSmmFJI4GnUvA%Ui5Syl}!UF@BWpiZJCYJmXusk!x zw4GgKQHVzoyKkm(0Z&6?gT5t0TRVeLmk?KvK`RprBMTFQnzXDEuOzQ-D~koQ1q%bu zvgJH_t&EG989TfAh4{5suU#)8C9ljW&Z#qh;bI2vqsO?lCQO>bpsAsL;bLn?o7c7L JH=G<9tN}1wpSu76 literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_failed.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_failed.gif new file mode 100644 index 0000000000000000000000000000000000000000..de59bac205fc85a6b18edf05a4ffbe8afe392b04 GIT binary patch literal 374 zcmZ?wbhEHb6krfwxXQrrGmk8dZet4&&0m%6dBaC^62yRYS>NZbA>*QtrV z^Roh%X;>EkuwW2HZ|vNX?LHSQeEOde^&j@t&8eP{o1R1 zn#+AB)_e5Sdd+Qho!;cOq2F#zkHhjVr$rskyH}K*-Zy8<1l#{$z<>c1f3h$#Fjz9^ zfMh^^VqlwmV2(k#wp9O7#lizQR{5tS4hS(utZ$eR#HQ)0@W8-j*&I%_i6v12f@h|f zwz7*X3h^jn_08liU}|V=(6{7nYv&f~5@PK!Xysw!XXD{kla^KDl;qTHWwYS5VB_Xk zwwyz+m46X0e`hzJ5TEwywd*CM(S#;(vT+GdW^ccI=gh^AlH8s>PTx{)V^SXBZ JhLa)X#icV0g`|M<4mw3vi-wMpyhQa3ghZtpgn7_8UsYdR&|a#Ezz>_prCD9;5Mu2U0z z=Vt{j$q!vr5Hu$@U`AH-s*3nE)iF!TB4-w4Y--Nk((XPtrMkqwuGFu(IH0}Cr@7pB zV!cOCt=HUE*Xd1e8~W|m^f)Z+$;W_50`V z`u6$!-0SAgqqJDKwhk8tdcTJIhNQ`|-orOi0f<~~9KCFyDr;0+Nh(o)mcFVq;w2(dj|NsC0 z{{R30A^8LW002G!EC2ui01yBW000J=K%daZD;kf*A#uQLI(bSPV8Z}duK=6!woow^ z;PB$6#0fBrbXvd=;FP+=sAS4$Qu0JjxeJ5>fPsKCJ`je75DkhA1&lR?6Oj`S5Gx=e zCkP%0GLVrMJrD<@qz5yF5~)2EiHiyi3NVE|7ZyDd5FH;RC aFNF~fJrTz)EiBg8g@}eq+}++nK>$0S@UV3N literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_run.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_run.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad88296bc79998fb3902b6c287f04170712572c4 GIT binary patch literal 594 zcmZ?wbhEHb6krfwc*elMz@N_`T)-e%{Nv{z28B`vjf(f5e}De==jX3K&))ue`{@^h zVfE9uKVN?M_4?zlk6(X3fB)qE}VKuc?k%QWiP0AY)T= z?w0ntJyUjGKjJ<&rMkqwuGFu+%BQ*9chjogiS-^mwO(^370zvSo!;cOq2F#zkHhjV zr$rskTNh*=+}N>Yg6;qR|AAf~3_$TG3nK$V5Q7fLF`zhMU|-)5)D#rh+ScCM+``e* z+ZWj7&8(%$JZ(C&w?wm#sI98#!bPG!;^Ixd?CPp(*08Ix`-&-u1^M%vSy*al+U(%> z6H$>D31Bl}J9+A)r;xI;tdOvs+SRLEYFu92N_Sr*-nWw#n<>fByaX+n=Am{GKxfdHwAC+Z^fx(zT2c#C{CkD2z12YT6 zw59r+4ov9Cu$t|8z{u=I0^1EolWkKX!z8*bvL@=rv-76O9+ipnzOkgl$@RJLjZ3K# zl8e|H+4Q`1`4j>rCHcB_y>)~Fl~go^%lc3KZC}a~H31APXxCH#ZkICpYT>W5yuwv**sAb7Zgv04VB})Bpeg literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_aborted.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_aborted.gif new file mode 100644 index 0000000000000000000000000000000000000000..7cd107cdc86cd1c190cebbe68774a8bc2a1a0f78 GIT binary patch literal 376 zcmZ?wbhEHb6krfwxXQqAQcU%py#9;a@)t!lZ+oWw`1$Ak=ik46|NZ&v&%4jRzkL7m z^zF}=AAWuM_UHT0KhNI%eDmqohp&IWeE^l0ZfN&bs-V^>#ZZfah6X@_x>Uv-K9;(0C2l|J=le*1T?oLKMCRqZve&3Ss0 z+wRphXAUi0-Q%#d)9KprMO!A=Zs@Z+y{Y2FhKidf7XAkV1{^@~CkrD3gE@l^NFL-T z2DYgOqH{b{?)7;nCY^LSGRZ^IsW|h}0{8I7s25@hH*R|~?TS%3`lZ+PW{usH$jLu* zG@ZI?&N}6u%42A3VqlMn(`#U2VPs)q;7d(U*Kc4kV>V-95S7dqkrdHtV4T6s$iOAX z#wNT*d-2lcys{D!0^2mEPM^sjs3ar9qr{`x+1<;)$$grin_sn|xlvt3`PwzL#9QW$ G4AuaMsjGPa literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_failed.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_failed.gif new file mode 100644 index 0000000000000000000000000000000000000000..d247a8fef52b61b9a9274093ce7e17792d68afff GIT binary patch literal 376 zcmZ?wbhEHb6krfwxXQrr`tbG7m+!w_(k8zD0#xw(+s{A0|NOo4`q}x%w*#kT7jExv z+cv{`dbIPLB>%;^v8yXHH#M)kw8OZ`ue!v4@w}GiN}u{Nzx}&cPOSIns`i@K<~+U0 zZTIS$Gl!P0?r~V!>2&S*qAe3_H}u(^-c)g7L&eP#3;%-w0}i10lZBCi!JI({BoFcv z1KZRC(K#L}_xd~@CY+QxGRfnnLviM%1@7VvTrZdsZrs*p+7+X8^h>Yn%^JHYk&}Ps zh&r{_oOQ}QmB-!K#LW~Fr`N#4Cd9_W&6S#-uHV3B#%spLEh?EWA}ONPAT)zlh?`Z8 zkx_V!_Tr_>Ib|gz__t|Hoj#LWKuJc1Ly1GPv%8m@h5a-iJD+MpbECS7^0jMfiMPxh G8LRp03 literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_notrun.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_notrun.gif new file mode 100644 index 0000000000000000000000000000000000000000..5198579fd660e0a51796d26e95003dc973bf03b4 GIT binary patch literal 358 zcmZ?wbhEHb6krfwxXQrrhoBba8jgW(us)&HfA&}aOZE}dcouraf#h9Qb*vZN#|mqBCf#6Ki{Y*H99zX z<@R|-eVo#%OU8{L%vV*D8xHE!Idvs5uo`i#WOn-Jxzq_fC ze@KdZN}h&8mx4ySt9;DDrK^lUrHMk;$D*{5J+O{G%d&XLuz17!fIA%=I~W!SA`=q}w=IAgJ3AB?77QmLAqOW1E`S#l cI~TwN2GI%z3Mznufh;K~+}tZ+;5l>n){9{oOW`Bag*PwWqs8p{?jMqHCOu7m-$Vs_votjn%Cw$y~%BL zkHgYVrvpnP)F5LJ;E zyK8UTV-rknr( literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/aborted_counter.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/aborted_counter.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f12861d51bc62e26cf86a61b7657a6288b28e8f GIT binary patch literal 82 zcmZ?wbhEHbWM|-DSj4~(Sh9@8AkV*WVL;JBm$Zrh!GM8*LGdRGBLf2)gAS0*08-1q gEH1H2%fUe-z>Tr%hU2GqjH!u@%${c^F)&yI01tE+#Q*>R literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/failed_counter.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/failed_counter.gif new file mode 100644 index 0000000000000000000000000000000000000000..c112416d5acd1b8df36ff7dc3c4659da0b89f1f9 GIT binary patch literal 82 zcmZ?wbhEHbWM|-DSj50^QcU%py#9;a@)t!lZ+oWw2LlEM2F0H&j0_BH3_3tI14u0c gvpB~tEfE)uAU8#=8-kzSF{CCoFngYv#K2$;0CKV!@&Et; literal 0 HcmV?d00001 diff --git a/testsrunner/org.eclipse.cdt.testsrunner/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner/plugin.properties new file mode 100644 index 00000000000..d968486593f --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/plugin.properties @@ -0,0 +1,30 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +pluginName=C/C++ Development Tools Tests Running Support +providerName=Eclipse CDT + +MainLaunchTab.name=Main +ArgumentsLaunchTab.name=Arguments +CTestingLaunchTab.name=C/C++ Testing +EnvironmentLaunchTab.name=Environment +DebuggerLaunchTab.name=Debugger +SourceLookupLaunchTab.name=Source +CommonLaunchTab.name=Common +RefreshLaunchTab.name=Refresh + +ResultsView.name=C/C++ Unit + +CPPUnitLaunchConfigurationType.name=C/C++ Unit + +CPPUnitLaunch.name=Standard C/C++ Tests Launcher +CPPUnitLaunch.description=Run C/C++ tests optionally under control of the standard debugger. +CPPUnitLaunchDSF.name=GDB (DSF) C/C++ Tests Launcher +CPPUnitLaunchDSF.description=Run C/C++ Tests under control of GDB debugger integrated using the Debugger Services Framework (DSF). diff --git a/testsrunner/org.eclipse.cdt.testsrunner/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner/plugin.xml new file mode 100644 index 00000000000..13d29059119 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/plugin.xml @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner/pom.xml new file mode 100644 index 00000000000..f3961df2424 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 8.1.0-SNAPSHOT + ../../pom.xml + + + 7.0.0-SNAPSHOT + org.eclipse.cdt.testsrunner + eclipse-plugin + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd b/testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd new file mode 100644 index 00000000000..ca160a18d05 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd @@ -0,0 +1,178 @@ + + + + + + + + + Defines an extestion point for the Tests Runner provider plug-in. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the tests runner that will be shown to user. + + + + + + + + + + Class implementing test runner functionality (org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider) + + + + + + + + + + Short description of the tests runner that will be shown to user + + + + + + + + + + Internal unique name of the tests runner + + + + + + + + + + + + Should be True if Tests Runner can generate a multiple tests filter for single test module launch. In this case rerun of multiple tests or test suites will be available and a few test items may be passed to configureLaunchParameters(). It is False by default. + + + + + + + Defines whether tests execution time are provided by testing framework. Otherwise turns on time measurement in Tests Runner Core. It is less accurate, but useful if testing framework does not provide time measurement. + + + + + + + Defines what stream (output or error) should be used to read the data from the testing process. Output is used by default. + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + + + + + Copyright (c) 2011 Anton Gorenkov. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java new file mode 100644 index 00000000000..0e5ee47fbb9 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal; + +import java.net.URL; +import java.util.HashSet; + +import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProvidersManager; +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerConstants; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchDelegate; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class TestsRunnerPlugin extends AbstractUIPlugin { + + /** The plug-in ID. */ + private static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner"; //$NON-NLS-1$ + + /** The path to the plugin icons */ + private static final IPath ICONS_PATH = new Path("$nl$/icons"); //$NON-NLS-1$ + + /** Plug-in instance. */ + private static TestsRunnerPlugin plugin; + + private TestsRunnerProvidersManager testsRunnerProvidersManager = new TestsRunnerProvidersManager(); + private TestingSessionsManager testingSessionsManager = new TestingSessionsManager(testsRunnerProvidersManager); + + + public TestsRunnerPlugin() { + super(); + plugin = this; + } + + /** + * Returns the Tests Runner Plug-in instance + * + * @return the plug-in instance + */ + public static TestsRunnerPlugin getDefault() { + return plugin; + } + + /** Convenience method which returns the unique identifier of this plug-in. */ + public static String getUniqueIdentifier() { + return PLUGIN_ID; + } + + /** + * Logs the specified status with this plug-in's log. + * + * @param status status to log + */ + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + + /** + * Logs an internal error with the specified message. + * + * @param message the error message to log + */ + public static void logErrorMessage(String message) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null)); + } + + /** + * Logs an internal error with the specified throwable + * + * @param e the exception to be logged + */ + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e)); + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + + setDefaultLaunchDelegates(); + } + + @Override + public void stop(BundleContext context) throws Exception { + super.stop(context); + } + + /** + * Access the plugin's Testing Sessions Manager instance. + * + * @return sessions manager + */ + public TestingSessionsManager getTestingSessionsManager() { + return testingSessionsManager; + } + + /** + * Access the plugin's Test Runners manager instance. + * + * @return tests runners manager + */ + public TestsRunnerProvidersManager getTestsRunnerProvidersManager() { + return testsRunnerProvidersManager; + } + + /** + * Returns the descriptor for image with relativePath path. + * + * @param relativePath path relative to ICONS_PATH + * @return image descriptor + */ + static public ImageDescriptor getImageDescriptor(String relativePath) { + return getDefault().getImageDescriptorImpl(relativePath); + } + + /** + * Returns the descriptor for image with relativePath path. + * + * @param relativePath path relative to ICONS_PATH + * @return image descriptor + */ + private ImageDescriptor getImageDescriptorImpl(String relativePath) { + IPath path = ICONS_PATH.append(relativePath); + return createImageDescriptor(getDefault().getBundle(), path, true); + } + + /** + * Returns the image with the specified path. + * + * @param path path + * @return image image + */ + public static Image createAutoImage(String path) { + return getDefault().createAutoImageImpl(path); + } + + /** + * Returns the image with the specified path. + * + * @param path path + * @return image image + */ + private Image createAutoImageImpl(String path) { + Image image = getImageRegistry().get(path); + if (image == null) { + image = getImageDescriptor(path).createImage(); + getImageRegistry().put(path, image); + } + return image; + } + + /** + * Creates an image descriptor for the given path in a bundle. The path can + * contain variables like $NL$. If no image could be found, + * useMissingImageDescriptor decides if either the 'missing + * image descriptor' is returned or null. + * + * @param bundle a bundle + * @param path path in the bundle + * @param useMissingImageDescriptor if true, returns the shared + * image descriptor for a missing image. Otherwise, returns + * null if the image could not be found + * @return an {@link ImageDescriptor}, or null iff there's no + * image at the given location and useMissingImageDescriptor is + * true + */ + private ImageDescriptor createImageDescriptor(Bundle bundle, IPath path, boolean useMissingImageDescriptor) { + URL url = FileLocator.find(bundle, path, null); + if (url != null) { + return ImageDescriptor.createFromURL(url); + } + if (useMissingImageDescriptor) { + return ImageDescriptor.getMissingImageDescriptor(); + } + return null; + } + + /** + * Setup the launch delegate with id delegateId as default for + * launch configuration type cfgType for mode + * launch mode. + * + * @param cfgType launch configuration type + * @param delegateId unique identifier of the launch delegate + * @param mode launch mode + */ + private void setDefaultLaunchDelegate(ILaunchConfigurationType cfgType, String delegateId, String mode) { + HashSet modes = new HashSet(); + modes.add(mode); + try { + if (cfgType.getPreferredDelegate(modes) == null) { + ILaunchDelegate[] delegates = cfgType.getDelegates(modes); + for (ILaunchDelegate delegate : delegates) { + if (delegateId.equals(delegate.getId())) { + cfgType.setPreferredDelegate(modes, delegate); + break; + } + } + } + } catch (CoreException e) { + log(e); + } + } + + /** + * Sets up the default launch delegates for the Tests Runner's launch configuration type. + */ + private void setDefaultLaunchDelegates() { + ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfigurationType configurationType = launchMgr.getLaunchConfigurationType(ITestsRunnerConstants.LAUNCH_CONFIGURATION_TYPE_ID); + + setDefaultLaunchDelegate(configurationType, ITestsRunnerConstants.PREFERRED_DEBUG_TESTS_LAUNCH_DELEGATE, ILaunchManager.DEBUG_MODE); + setDefaultLaunchDelegate(configurationType, ITestsRunnerConstants.PREFERRED_RUN_TESTS_LAUNCH_DELEGATE, ILaunchManager.RUN_MODE); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java new file mode 100644 index 00000000000..c0bef982048 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +import org.eclipse.cdt.testsrunner.launcher.BaseTestsLaunchDelegate; + + +/** + * Launch delegate implementation that redirects its queries to CDI. + */ +public class CdiRunTestsLaunchDelegate extends BaseTestsLaunchDelegate { + + @Override + public String getPreferredDelegateId() { + return "org.eclipse.cdt.cdi.launch.localCLaunch"; //$NON-NLS-1$ + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java new file mode 100644 index 00000000000..7f68f38d047 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +import org.eclipse.cdt.testsrunner.launcher.BaseTestsLaunchDelegate; + + +/** + * Launch delegate implementation that redirects its queries to DSF. + */ +public class DsfGdbRunTestsLaunchDelegate extends BaseTestsLaunchDelegate { + + @Override + public String getPreferredDelegateId() { + return "org.eclipse.cdt.dsf.gdb.launch.localCLaunch"; //$NON-NLS-1$ + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java new file mode 100644 index 00000000000..fa08017b1b0 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2012 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +/** + * Constants used for attributes in CDT Unit Testing Support launch + * configurations. + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface ITestsLaunchConfigurationConstants { + + public static final String CDT_TESTS_LAUNCH_ID = "org.eclipse.cdt.testsrunner.launch"; //$NON-NLS-1$ + + /** + * Launch configuration attribute key. The value is a string specifying + * tests runner string unique identifier + */ + public static final String ATTR_TESTS_RUNNER = CDT_TESTS_LAUNCH_ID + ".TESTS_RUNNER"; //$NON-NLS-1$ + + /** + * Launch configuration attribute key. The value is a string list specifying + * tests paths to run + */ + public static final String ATTR_TESTS_FILTER = CDT_TESTS_LAUNCH_ID + ".TESTS_FILTER"; //$NON-NLS-1$ + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java new file mode 100644 index 00000000000..2b66e11909f --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +import org.eclipse.osgi.util.NLS; + +public class LauncherMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.launcher.LauncherMessages"; //$NON-NLS-1$ + public static String BaseTestsLaunchDelegate_invalid_tests_runner; + public static String BaseTestsLaunchDelegate_tests_runner_load_failed; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, LauncherMessages.class); + } + + private LauncherMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties new file mode 100644 index 00000000000..2208efc2bce --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +BaseTestsLaunchDelegate_invalid_tests_runner=Tests Runner is not specified or invalid +BaseTestsLaunchDelegate_tests_runner_load_failed=Tests Runner cannot be instantiated diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java new file mode 100644 index 00000000000..5a99ec4bd20 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Wraps the underline process and prevent accessing to its output or error stream. + * This wrapping is necessary to prevent handling the test module output by Console + * because we want to handle it here. + * + */ +class ProcessWrapper extends Process { + + /** The real underlying process. */ + private Process wrappedProcess; + + /** The flag shows whether input stream should be replaced with empty dummy. */ + private boolean hideInputStream; + + /** The flag shows whether error stream should be replaced with empty dummy. */ + private boolean hideErrorStream; + + + /** Buffer for empty dummy stream. */ + private byte buffer[] = new byte[0]; + + /** Empty dummy stream. */ + private InputStream emptyInputStream = new ByteArrayInputStream(buffer); + + /** + * The synchronization event: before it happens waitFor() will + * not be called on underlying process object. See also the comments in + * waitFor(). + */ + private Object waitForSync = new Object(); + + /** + * Flag that shows that process output was not processed yet so the IO + * streams could not be closed yet. + */ + private boolean streamsClosingIsAllowed = false; + + + /** + * The constructor + * + * @param wrappedProcess underlying process + * @param hideInputStream process input stream should be hidden + * @param hideErrorStream process error stream should be hidden + */ + public ProcessWrapper(Process wrappedProcess, boolean hideInputStream, boolean hideErrorStream) { + this.wrappedProcess = wrappedProcess; + this.hideInputStream = hideInputStream; + this.hideErrorStream = hideErrorStream; + } + + @Override + public void destroy() { + wrappedProcess.destroy(); + } + + @Override + public int exitValue() { + return wrappedProcess.exitValue(); + } + + @Override + public InputStream getErrorStream() { + return hideErrorStream ? emptyInputStream : wrappedProcess.getErrorStream(); + } + + @Override + public InputStream getInputStream() { + return hideInputStream ? emptyInputStream : wrappedProcess.getInputStream(); + } + + @Override + public OutputStream getOutputStream() { + return wrappedProcess.getOutputStream(); + } + + @Override + public int waitFor() throws InterruptedException { + // NOTE: implementation of waitFor() in Spawner will close streams after process is terminated, + // so we should wait with this operation until we process all stream data + synchronized (waitForSync) { + if (!streamsClosingIsAllowed) { + waitForSync.wait(); + } + } + return wrappedProcess.waitFor(); + } + + /** + * Sets up the flag the allows IO streams closing. + */ + public void allowStreamsClosing() { + synchronized (waitForSync) { + streamsClosingIsAllowed = true; + waitForSync.notifyAll(); + } + } + +} \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java new file mode 100644 index 00000000000..ce498d5bf2b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +import java.io.InputStream; +import java.util.Map; + +import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants; +import org.eclipse.cdt.dsf.gdb.launching.GDBProcess; +import org.eclipse.cdt.dsf.gdb.launching.InferiorRuntimeProcess; +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.model.TestingSession; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.IProcessFactory; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.core.model.RuntimeProcess; + +/** + * Custom testing process factory allows to handle the output stream of the + * testing process and prevent it from output to Console. + */ +public class TestingProcessFactory implements IProcessFactory { + + /** + * Runs data processing for the testing process and close IO stream when it + * is done. + */ + private class TestingSessionRunner implements Runnable { + + private TestingSession testingSession; + private InputStream iStream; + private ProcessWrapper processWrapper; + + TestingSessionRunner(TestingSession testingSession, InputStream iStream, ProcessWrapper processWrapper) { + this.testingSession = testingSession; + this.iStream = iStream; + this.processWrapper = processWrapper; + } + + @Override + public void run() { + try { + testingSession.run(iStream); + } + finally { + // Streams should be closed anyway to avoid testing process hang up + processWrapper.allowStreamsClosing(); + } + } + } + + /** + * Creates a wrapper for the specified process to handle its input or error + * stream. + * + * @param launch launch + * @param process process to wrap + * @return wrapped process + * @throws CoreException + */ + private Process wrapProcess(ILaunch launch, Process process) throws CoreException { + TestingSession testingSession = TestsRunnerPlugin.getDefault().getTestingSessionsManager().newSession(launch); + ITestsRunnerProviderInfo testsRunnerProvider = testingSession.getTestsRunnerProviderInfo(); + InputStream iStream = + testsRunnerProvider.isOutputStreamRequired() ? process.getInputStream() : + testsRunnerProvider.isErrorStreamRequired() ? process.getErrorStream() : null; + ProcessWrapper processWrapper = new ProcessWrapper(process, testsRunnerProvider.isOutputStreamRequired(), testsRunnerProvider.isErrorStreamRequired()); + Thread t = new Thread(new TestingSessionRunner(testingSession, iStream, processWrapper)); + t.start(); + return processWrapper; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public IProcess newProcess(ILaunch launch, Process process, String label, Map attributes) { + + try { + // Mimic the behavior of DSF GDBProcessFactory. + if (attributes != null) { + Object processTypeCreationAttrValue = attributes.get(IGdbDebugConstants.PROCESS_TYPE_CREATION_ATTR); + if (IGdbDebugConstants.GDB_PROCESS_CREATION_VALUE.equals(processTypeCreationAttrValue)) { + return new GDBProcess(launch, process, label, attributes); + } + + if (IGdbDebugConstants.INFERIOR_PROCESS_CREATION_VALUE.equals(processTypeCreationAttrValue)) { + return new InferiorRuntimeProcess(launch, wrapProcess(launch, process), label, attributes); + } + + // Probably, it is CDI creating a new inferior process + } else { + return new RuntimeProcess(launch, wrapProcess(launch, process), label, attributes); + } + + } catch (CoreException e) { + TestsRunnerPlugin.log(e); + } + + return null; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java new file mode 100644 index 00000000000..5f5927b3c91 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; + +/** + * Provides access to the information about the Tests Runner provider plug-in + * (id, name, description, supported features set). Also provides the access to + * ITestsRunnerProvider interface (the main interface of Tests Runner + * provider plug-in). + */ +public class TestsRunnerProviderInfo implements ITestsRunnerProviderInfo { + + private static final String TESTS_RUNNER_FEATURES_ELEMENT = "features"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_FEATURE_MULTIPLE_TEST_FILTER_ATTRIBUTE = "multipleTestFilter"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_FEATURE_TESTING_TIME_MEASUREMENT_ATTRIBUTE = "testingTimeMeasurement"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_FEATURE_DATA_STREAM_ATTRIBUTE = "dataStream"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_ID_ATTRIBUTE = "id"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_NAME_ATTRIBUTE = "name"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$ + private static final String TESTS_RUNNER_ERROR_STREAM_VALUE = "error"; //$NON-NLS-1$ + + /** Configuration element of the Tests Runner provider plug-ins extension point. */ + private IConfigurationElement element; + + /** + * The constructor. + * + * @param element configuration element of the Tests Runner provider plug-ins extension point + */ + public TestsRunnerProviderInfo(IConfigurationElement element) { + this.element = element; + } + + @Override + public String getName() { + return element.getAttribute(TESTS_RUNNER_NAME_ATTRIBUTE); + } + + @Override + public String getId() { + return element.getAttribute(TESTS_RUNNER_ID_ATTRIBUTE); + } + + @Override + public String getDescription() { + String result = element.getAttribute(TESTS_RUNNER_DESCRIPTION_ATTRIBUTE); + return result == null ? "" : result; //$NON-NLS-1$ + } + + /** + * Instantiates Tests Runner provider plug-in and return its main interface. + * + * @note Instantiated Tests Runner provider plug-in objects are not cached + * and are instantiated as much times as + * instantiateTestsRunnerProvider() is called. + * + * @return Tests Runner provider plug-in main interface + */ + public ITestsRunnerProvider instantiateTestsRunnerProvider() { + try { + Object object = element.createExecutableExtension(TESTS_RUNNER_CLASS_ATTRIBUTE); + if (object instanceof ITestsRunnerProvider) { + return (ITestsRunnerProvider)object; + } + } catch (CoreException e) { + TestsRunnerPlugin.log(e); + } + return null; + } + + /** + * Provides an access to the 'features' node of Tests Runner provider + * plug-in configuration element. + * + * @return 'features' configuration element + */ + private IConfigurationElement getFeatures() { + IConfigurationElement[] featuresElements = element.getChildren(TESTS_RUNNER_FEATURES_ELEMENT); + if (featuresElements.length == 1) { + return featuresElements[0]; + } + return null; + } + + /** + * Provides an access to the value of the feature with specified name. + * + * @param featureName + * @return feature value or null if there is no features described or there + * is no feature with such name + */ + private String getFeatureAttributeValue(String featureName) { + IConfigurationElement features = getFeatures(); + if (features != null) { + return features.getAttribute(featureName); + } + return null; + } + + /** + * Provides an access to the boolean value of the feature with the specified + * name. If the feature with such name cannot be accessed or it contains + * invalid boolean value, the default value will be returned. + * + * @param featureName + * @param defaultValue + * @return feature value or null if there is no features described or there + * is no feature with such name + */ + private boolean getBooleanFeatureValue(String featureName, boolean defaultValue) { + String attrValue = getFeatureAttributeValue(featureName); + if (attrValue != null) { + return Boolean.parseBoolean(attrValue); + } + return defaultValue; + } + + @Override + public boolean isAllowedMultipleTestFilter() { + return getBooleanFeatureValue(TESTS_RUNNER_FEATURE_MULTIPLE_TEST_FILTER_ATTRIBUTE, false); + } + + /** + * Returns whether test execution time measurement should be performed by + * the Tests Runner Plug-in. + * + * @note It should be used only if testing framework does not provide + * execution time measurement, cause measurement by Tests Runner Plug-in is + * not very precise (it also takes into account output processing & internal + * model building time). + * + * @return whether testing time measurement should be done by Tests Runner + * Plug-in + */ + public boolean isAllowedTestingTimeMeasurement() { + return getBooleanFeatureValue(TESTS_RUNNER_FEATURE_TESTING_TIME_MEASUREMENT_ATTRIBUTE, false); + } + + @Override + public boolean isOutputStreamRequired() { + return !isErrorStreamRequired(); + } + + @Override + public boolean isErrorStreamRequired() { + String attrValue = getFeatureAttributeValue(TESTS_RUNNER_FEATURE_DATA_STREAM_ATTRIBUTE); + if (attrValue != null) { + return attrValue.equals(TESTS_RUNNER_ERROR_STREAM_VALUE); + } + return false; + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java new file mode 100644 index 00000000000..39f216ab35b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.launcher; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.debug.core.ILaunchConfiguration; + +/** + * Collects the data from the Tests Runner provider plug-in extension points and + * provides the convenient access to it. + */ +public class TestsRunnerProvidersManager { + + /** Tests Runner Plug-ins extension point ID. */ + private static final String TESTS_RUNNER_EXTENSION_POINT_ID = "org.eclipse.cdt.testsrunner.TestsRunner"; //$NON-NLS-1$ + + /** Tests Runner Plug-ins information collection. */ + private TestsRunnerProviderInfo[] testsRunnerProviders = null; + + + /** + * Provides access to information about all registered Tests Runner + * Plug-ins. + * + * @return array of tests runner plug-ins descriptors + */ + public TestsRunnerProviderInfo[] getTestsRunnersProviderInfo() { + if (testsRunnerProviders == null) { + // Initialize tests runners info + List testsRunnerProvidersList = new ArrayList(); + for (IConfigurationElement element : Platform.getExtensionRegistry().getConfigurationElementsFor(TESTS_RUNNER_EXTENSION_POINT_ID)) { + testsRunnerProvidersList.add(new TestsRunnerProviderInfo(element)); + } + testsRunnerProviders = testsRunnerProvidersList.toArray(new TestsRunnerProviderInfo[testsRunnerProvidersList.size()]); + } + return testsRunnerProviders; + } + + /** + * Provides access to information about Tests Runner Plug-in referred in the + * specified launch configuration. + * + * @return tests runner plug-in descriptor + */ + public TestsRunnerProviderInfo getTestsRunnerProviderInfo(ILaunchConfiguration launchConf) throws CoreException { + String testsRunnerId = launchConf.getAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, (String)null); + return getTestsRunnerProviderInfo(testsRunnerId); + } + + /** + * Provides access to information about Tests Runner Plug-in with the + * specified ID. + * + * @return tests runner plug-in descriptor + */ + private TestsRunnerProviderInfo getTestsRunnerProviderInfo(String testsRunnerProviderId) { + if (testsRunnerProviderId != null) { + for (TestsRunnerProviderInfo testsRunnerProvider : getTestsRunnersProviderInfo()) { + if (testsRunnerProvider.getId().equals(testsRunnerProviderId)) { + return testsRunnerProvider; + } + } + } + return null; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java new file mode 100644 index 00000000000..578ed7b2f07 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import org.eclipse.cdt.testsrunner.model.ITestingSession; + +/** + * Testing sessions manager listener is notified of testing sessions management. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestingSessionsManagerListener { + + /** + * Notifies the listener that the specified testing session was activated. + * + * @param testingSession the activated testing session + */ + void sessionActivated(ITestingSession testingSession); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java new file mode 100644 index 00000000000..b690f1cfa38 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import org.eclipse.osgi.util.NLS; + +public class ModelMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.model.ModelMessages"; //$NON-NLS-1$ + public static String TestingSession_finished_status; + public static String TestingSession_name_format; + public static String TestingSession_starting_status; + public static String TestingSession_stopped_status; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, ModelMessages.class); + } + + private ModelMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties new file mode 100644 index 00000000000..c57df6a1589 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties @@ -0,0 +1,14 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +TestingSession_name_format={0} ({1}) +TestingSession_finished_status=Finished after {0} seconds +TestingSession_starting_status=Starting... +TestingSession_stopped_status=Testing was stopped by user diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java new file mode 100644 index 00000000000..84e9db50d18 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestCase; + +/** + * Represents the test case (test) of the test hierarchy. + */ +public class TestCase extends TestItem implements ITestCase { + + /** Test case status (failed, passed, ...). */ + private Status status; + + /** Test case execution time. */ + private int testingTime; + + /** + * The messages that were generated by testing framework during test + * running. + */ + private List testMessages = new ArrayList(); + + + public TestCase(String name, TestSuite parent) { + super(name, parent); + reset(); + } + + @Override + public Status getStatus() { + return status; + } + + @Override + public int getTestingTime() { + return testingTime; + } + + @Override + public TestMessage[] getTestMessages() { + return testMessages.toArray(new TestMessage[testMessages.size()]); + } + + @Override + public void visit(IModelVisitor visitor) { + visitor.visit(this); + for (TestMessage message : testMessages) { + message.visit(visitor); + } + visitor.leave(this); + } + + /** + * Resets the test case to the default state. + */ + public void reset() { + status = Status.Skipped; + testingTime = 0; + testMessages.clear(); + } + + /** + * Modifies the status of the test case. + * + * @param status new test status + */ + public void setStatus(Status status) { + this.status = status; + } + + /** + * Modifies the execution time of the test case. + * + * @param testingTime new test execution time + */ + public void setTestingTime(int testingTime) { + this.testingTime = testingTime; + } + + /** + * Adds a new test message to the test case. + * + * @param testMessage message + */ + public void addTestMessage(TestMessage testMessage) { + testMessages.add(testMessage); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java new file mode 100644 index 00000000000..55c775fda5a --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import org.eclipse.cdt.testsrunner.model.ITestItem; + +/** + * Common implementation for the structural item of test hierarchy (test suite + * or test case). + */ +public abstract class TestItem implements ITestItem { + + /** Test item has no children by default. */ + private static final ITestItem[] NO_CHILDREN = new ITestItem[0]; + + /** Test item name. */ + private final String name; + + /** Item parent test suite. May be null for root test suite. */ + private TestSuite parent; + + + public TestItem(String name, TestSuite parent) { + this.name = name; + this.parent = parent; + } + + @Override + public String getName() { + return name; + } + + @Override + public TestSuite getParent() { + return parent; + } + + @Override + public boolean hasChildren() { + return false; + } + + @Override + public ITestItem[] getChildren() { + return NO_CHILDREN; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java new file mode 100644 index 00000000000..afe8bfaae58 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import org.eclipse.cdt.testsrunner.model.ITestLocation; + +/** + * Represents the location of the test object. + */ +public class TestLocation implements ITestLocation { + + /** Stores the file name in which testing object is located. */ + private String file; + + /** Stores the line number on which testing object is located. */ + private int line; + + + public TestLocation(String file, int line) { + this.file = file; + this.line = line; + } + + @Override + public String getFile() { + return file; + } + + @Override + public int getLine() { + return line; + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java new file mode 100644 index 00000000000..4a5402f48fa --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestMessage; + +/** + * Represents the message that was produced during the testing process. + */ +public class TestMessage implements ITestMessage { + + /** Test message location. */ + private TestLocation location; + + /** Test message level */ + private Level level; + + /** Test message text */ + private String text; + + + public TestMessage(TestLocation location, Level level, String text) { + this.location = location; + this.level = level; + this.text = text; + } + + @Override + public TestLocation getLocation() { + return location; + } + + @Override + public Level getLevel() { + return level; + } + + @Override + public String getText() { + return text; + } + + @Override + public void visit(IModelVisitor visitor) { + visitor.visit(this); + visitor.leave(this); + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java new file mode 100644 index 00000000000..0db8d5af989 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java @@ -0,0 +1,480 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.eclipse.cdt.testsrunner.model.ITestModelAccessor; +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.ITestingSessionListener; +import org.eclipse.cdt.testsrunner.model.ITestCase; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestItem.Status; +import org.eclipse.cdt.testsrunner.model.ITestMessage.Level; +import org.eclipse.cdt.testsrunner.model.ITestSuite; + +/** + * Manages the testing model (creates, fill and update it) and notifies the + * listeners about updates. + */ +public class TestModelManager implements ITestModelUpdater, ITestModelAccessor { + + /** + * Name of the root test suite. + * + * @note Root test suite is invisible (only its children are visible), so + * the name is not important. + */ + public static final String ROOT_TEST_SUITE_NAME = ""; //$NON-NLS-1$ + + /** Stack of the currently entered (and not existed) test suites. */ + private Stack testSuitesStack = new Stack(); + + /** + * Currently running test case. There are no nested test cases, so the + * collection is not necessary. + */ + private TestCase currentTestCase = null; + + /** + * The mapping of test suite object to the index on which it was inserted to + * the parent. + * + * @note Test suites presence in this map means that test suite was visited + * during the testing process (not visited test suites are removed when + * testing is finished cause they are considered as renamed or removed). + * @note Test suite insert position is important for insertion algorithm. + */ + private Map testSuitesIndex = new HashMap(); + + /** Listeners collection. */ + private List listeners = new ArrayList(); + + /** Flag stores whether test execution time should be measured for the session. */ + private boolean timeMeasurement = false; + + /** Stores the test case start time or 0 there is no currently running test case. */ + private long testCaseStartTime = 0; + + /** Instance of the insertion algorithm for test suites. */ + private TestSuiteInserter testSuiteInserter = new TestSuiteInserter(); + + /** Instance of the insertion algorithm for test cases. */ + private TestCaseInserter testCaseInserter = new TestCaseInserter(); + + + /** + * Builds current tests hierarchy from the other one (copies only necessary + * information). + */ + private class HierarchyCopier implements IModelVisitor { + + @Override + public void visit(ITestSuite testSuite) { + // Do not copy root test suite + if (testSuite.getParent() != null) { + enterTestSuite(testSuite.getName()); + } + } + + @Override + public void leave(ITestSuite testSuite) { + // Do not copy root test suite + if (testSuite.getParent() != null) { + exitTestSuite(); + } + } + + @Override + public void visit(ITestCase testCase) { + enterTestCase(testCase.getName()); + setTestStatus(TestCase.Status.NotRun); + } + + @Override + public void leave(ITestCase testCase) { + exitTestCase(); + } + + @Override + public void visit(ITestMessage testMessage) {} + @Override + public void leave(ITestMessage testMessage) {} + } + + + /** + * Utility class: generalization of insertion algorithm for test suites and + * test cases. + * + *

+ * The algorithm tries to find the place where the new item should be + * inserted at. If the item with such name does not exist in the current top + * most test suite, it should be inserted at the current position. If it + * already exists (at the next or previous position) then it should be moved + * from there to the current one. + *

+ * + * @param test item type (test suite or test case) + */ + private abstract class TestItemInserter { + + /** + * Check whether item has the required type (test suite for suites inserter and + * test case for cases one). + * + * @param item test item to check + * @return whether item has the required type + */ + protected abstract boolean isRequiredTestItemType(TestItem item); + + /** + * Creates a new item type with the specified name and parent (test + * suite for suites inserter and test case for cases one). + * + * @param name name of the new test item + * @param parent parent for the new test item + * @return new test item + */ + protected abstract E createTestItem(String name, TestSuite parent); + + /** + * Save new test item in the tracking structures (suite in stack, case + * in current variable). Additional operations (e.g. listeners + * notification about item entering) can be done too. + * + * @param item new test item + */ + protected abstract void addNewTestItem(E item); + + + /** + * Returns the casted test item if it matches by name and type or + * null if it doesn't. + * + * @param item test item to check + * @param name test item name + * @return casted test item or null + */ + @SuppressWarnings("unchecked") + private E checkTestItem(TestItem item, String name) { + return (isRequiredTestItemType(item) && item.getName().equals(name)) ? (E)item : null; + } + + /** + * Returns the last insert index for the specified test suite. Returns 0 + * if test suite was not inserted yet. + * + * @param testSuite test suite to look up + * @return insert index or 0 + */ + private int getLastInsertIndex(TestSuite testSuite) { + Integer intLastInsertIndex = testSuitesIndex.get(testSuite); + return intLastInsertIndex != null ? intLastInsertIndex : 0; + } + + /** + * Notifies the listeners about children update of the specified test + * suite. + * + * @param suite updated test suite + */ + private void notifyAboutChildrenUpdate(ITestSuite suite) { + for (ITestingSessionListener listener : getListenersCopy()) { + listener.childrenUpdate(suite); + } + } + + /** + * Inserts the test item by the name. + * + * @param name test item name + */ + public void insert(String name) { + TestSuite currTestSuite = testSuitesStack.peek(); + int lastInsertIndex = getLastInsertIndex(currTestSuite); + List children = currTestSuite.getChildrenList(); + E newTestItem = null; + + // Optimization: Check whether we already pointing to the test suite with required name + try { + newTestItem = checkTestItem(children.get(lastInsertIndex), name); + } catch (IndexOutOfBoundsException e) {} + if (newTestItem != null) { + testSuitesIndex.put(currTestSuite, lastInsertIndex+1); + } + + // Check whether the suite with required name was later in the hierarchy + if (newTestItem == null) { + for (int childIndex = lastInsertIndex; childIndex < children.size(); childIndex++) { + newTestItem = checkTestItem(children.get(childIndex), name); + if (newTestItem != null) { + testSuitesIndex.put(currTestSuite, childIndex); + break; + } + } + } + + // Search in previous + if (newTestItem == null) { + for (int childIndex = 0; childIndex < lastInsertIndex; childIndex++) { + newTestItem = checkTestItem(children.get(childIndex), name); + if (newTestItem != null) { + children.add(lastInsertIndex, children.remove(childIndex)); + notifyAboutChildrenUpdate(currTestSuite); + break; + } + } + } + + // Add new + if (newTestItem == null) { + newTestItem = createTestItem(name, currTestSuite); + children.add(lastInsertIndex, newTestItem); + testSuitesIndex.put(currTestSuite, lastInsertIndex+1); + notifyAboutChildrenUpdate(currTestSuite); + } + if (!testSuitesIndex.containsKey(newTestItem)) { + testSuitesIndex.put(newTestItem, 0); + } + addNewTestItem(newTestItem); + } + + } + + + /** + * Utility class: insertion algorithm specialization for test suites. + */ + private class TestSuiteInserter extends TestItemInserter { + + @Override + protected boolean isRequiredTestItemType(TestItem item) { + return (item instanceof TestSuite); + } + + @Override + protected TestSuite createTestItem(String name, TestSuite parent) { + return new TestSuite(name, parent); + } + + @Override + protected void addNewTestItem(TestSuite testSuite) { + testSuitesStack.push(testSuite); + + // Notify listeners + for (ITestingSessionListener listener : getListenersCopy()) { + listener.enterTestSuite(testSuite); + } + } + } + + + /** + * Utility class: insertion algorithm specialization for test cases. + */ + private class TestCaseInserter extends TestItemInserter { + + @Override + protected boolean isRequiredTestItemType(TestItem item) { + return (item instanceof TestCase); + } + + @Override + protected TestCase createTestItem(String name, TestSuite parent) { + return new TestCase(name, parent); + } + + @Override + protected void addNewTestItem(TestCase testCase) { + currentTestCase = testCase; + testCase.setStatus(ITestItem.Status.Skipped); + + // Notify listeners + for (ITestingSessionListener listener : getListenersCopy()) { + listener.enterTestCase(testCase); + } + } + } + + + public TestModelManager(ITestSuite previousTestsHierarchy, boolean timeMeasurement) { + testSuitesStack.push(new TestSuite(ROOT_TEST_SUITE_NAME, null)); + if (previousTestsHierarchy != null) { + // Copy tests hierarchy + this.timeMeasurement = false; + previousTestsHierarchy.visit(new HierarchyCopier()); + } + this.timeMeasurement = timeMeasurement; + this.testSuitesIndex.clear(); + } + + /** + * Notifies the listeners that testing was started. + */ + public void testingStarted() { + // Notify listeners + for (ITestingSessionListener listener : getListenersCopy()) { + listener.testingStarted(); + } + } + + /** + * Removes not visited test items and notifies the listeners that testing + * was finished. + */ + public void testingFinished() { + // Remove all NotRun-tests and not used test suites (probably they were removed from test module) + getRootSuite().visit(new IModelVisitor() { + + @Override + public void visit(ITestSuite testSuite) { + List suiteChildren = ((TestSuite)testSuite).getChildrenList(); + for (Iterator it = suiteChildren.iterator(); it.hasNext();) { + TestItem item = it.next(); + if ((item instanceof ITestSuite && !testSuitesIndex.containsKey(item)) || + (item instanceof ITestCase && item.getStatus() == ITestItem.Status.NotRun)) { + it.remove(); + } + } + } + + @Override + public void visit(ITestMessage testMessage) {} + @Override + public void visit(ITestCase testCase) {} + @Override + public void leave(ITestSuite testSuite) {} + @Override + public void leave(ITestCase testCase) {} + @Override + public void leave(ITestMessage testMessage) {} + }); + testSuitesIndex.clear(); + + // Notify listeners + for (ITestingSessionListener listener : getListenersCopy()) { + listener.testingFinished(); + } + } + + @Override + public void enterTestSuite(String name) { + testSuiteInserter.insert(name); + } + + @Override + public void exitTestSuite() { + exitTestCase(); + TestSuite testSuite = testSuitesStack.pop(); + // Notify listeners + for (ITestingSessionListener listener : getListenersCopy()) { + listener.exitTestSuite(testSuite); + } + } + + @Override + public void enterTestCase(String name) { + testCaseInserter.insert(name); + if (timeMeasurement) { + testCaseStartTime = System.currentTimeMillis(); + } + } + + + @Override + public void setTestStatus(Status status) { + currentTestCase.setStatus(status); + } + + @Override + public void setTestingTime(int testingTime) { + currentTestCase.setTestingTime(testingTime); + } + + @Override + public void exitTestCase() { + if (currentTestCase != null) { + // Set test execution time (if time measurement is turned on) + if (timeMeasurement) { + int testingTime = (int)(System.currentTimeMillis()-testCaseStartTime); + currentTestCase.setTestingTime(currentTestCase.getTestingTime()+testingTime); + testCaseStartTime = 0; + } + TestCase testCase = currentTestCase; + currentTestCase = null; + // Notify listeners + for (ITestingSessionListener listener : getListenersCopy()) { + listener.exitTestCase(testCase); + } + } + } + + @Override + public void addTestMessage(String file, int line, Level level, String text) { + TestLocation location = (file == null || file.isEmpty() || line <= 0) ? null : new TestLocation(file, line); + currentTestCase.addTestMessage(new TestMessage(location, level, text)); + } + + @Override + public ITestSuite currentTestSuite() { + return testSuitesStack.peek(); + } + + + @Override + public ITestCase currentTestCase() { + return currentTestCase; + } + + @Override + public boolean isCurrentlyRunning(ITestItem item) { + return (item == currentTestCase && item != null) || testSuitesStack.contains(item); + } + + @Override + public TestSuite getRootSuite() { + return testSuitesStack.firstElement(); + } + + @Override + public void addChangesListener(ITestingSessionListener listener) { + synchronized (listeners) { + listeners.add(listener); + } + } + + @Override + public void removeChangesListener(ITestingSessionListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + /** + * Copies listeners before notifying them to avoid dead-locks. + * + * @return listeners collection copy + */ + private ITestingSessionListener[] getListenersCopy() { + synchronized (listeners) { + return listeners.toArray(new ITestingSessionListener[listeners.size()]); + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java new file mode 100644 index 00000000000..188f8142705 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestSuite; + +/** + * Represents the test suite of the tests hierarchy. + */ +public class TestSuite extends TestItem implements ITestSuite { + + /** + * Stores child test suites and test cases. + * + * @note Children order is important. + */ + private List children = new ArrayList(); + + + public TestSuite(String name, TestSuite parent) { + super(name, parent); + } + + @Override + public Status getStatus() { + Status result = Status.NotRun; + for (TestItem testItem : children) { + Status childStatus = testItem.getStatus(); + if (result.compareTo(childStatus) < 0) { + result = childStatus; + } + } + return result; + } + + @Override + public int getTestingTime() { + int result = 0; + for (TestItem testItem : children) { + result += testItem.getTestingTime(); + } + return result; + } + + @Override + public boolean hasChildren() { + return !children.isEmpty(); + } + + @Override + public TestItem[] getChildren() { + return children.toArray(new TestItem[children.size()]); + } + + @Override + public void visit(IModelVisitor visitor) { + visitor.visit(this); + for (TestItem testItem : children) { + testItem.visit(visitor); + } + visitor.leave(this); + } + + /** + * Returns list of children for the test suite. + * + * @return children list + */ + public List getChildrenList() { + return children; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java new file mode 100644 index 00000000000..f706fa302b2 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import java.io.InputStream; +import java.text.DateFormat; +import java.text.MessageFormat; +import java.util.Date; +import java.util.EnumMap; +import java.util.Map; + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestCase; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestItem.Status; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.eclipse.cdt.testsrunner.model.ITestModelAccessor; +import org.eclipse.cdt.testsrunner.model.ITestSuite; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.cdt.testsrunner.model.ITestingSessionListener; +import org.eclipse.cdt.testsrunner.model.TestingException; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.ILaunch; + +/** + * Stores the information about tests running. + */ +public class TestingSession implements ITestingSession { + + /** Launch object the is connected to the tests running. */ + private ILaunch launch; + + /** Information about used Tests Runner provider plug-in. */ + private TestsRunnerProviderInfo testsRunnerProviderInfo; + + /** Main interface to Tests Runner provider plug-in. */ + private ITestsRunnerProvider testsRunnerProvider; + + /** + * Test Model manager that is used to fill and update the model for the + * session. + */ + private TestModelManager modelManager; + + /** + * Total tests counter. It is -1 by default, that means that total tests + * count is not available. + * + * @see getTotalCounter() + */ + private int totalCounter = -1; + + /** Already finished tests counter. */ + private int currentCounter = 0; + + /** + * Test counters map by test status. They are used to quickly provide simple + * statistics without model scanning. + * + */ + private Map statusCounters = new EnumMap(ITestItem.Status.class); + + /** + * The flag stores whether the testing session contains errors at the + * moment. + * + * @see hasErrors() + */ + private boolean hasErrors = false; + + /** + * The flag stores whether the testing session was stopped by user. + * + * @see wasStopped() + */ + private boolean wasStopped = false; + + /** + * The flag stores whether the testing session has been finished (with or + * without errors). + */ + private boolean finished = false; + + /** Stores current status of the testing session. */ + private String statusMessage = ModelMessages.TestingSession_starting_status; + + /** Stores the time when the testing session was created. */ + private long startTime; + + + /** + * Counts the number of the test cases in tests hierarchy. + */ + private class TestCasesCounter implements IModelVisitor { + + public int result = 0; + + @Override + public void visit(ITestCase testCase) { + ++result; + } + + @Override + public void visit(ITestSuite testSuite) {} + @Override + public void visit(ITestMessage testMessage) {} + @Override + public void leave(ITestSuite testSuite) {} + @Override + public void leave(ITestCase testCase) {} + @Override + public void leave(ITestMessage testMessage) {} + } + + + /** + * The constructor. + * + * @param launch connected launch object + * @param testsRunnerProviderInfo the information about the tests runner + * @param previousSession is used to determine total tests count & for tests + * hierarchy reusing if it is considered as similar + */ + public TestingSession(ILaunch launch, TestsRunnerProviderInfo testsRunnerProviderInfo, TestingSession previousSession) { + this.launch = launch; + this.testsRunnerProviderInfo = testsRunnerProviderInfo; + this.testsRunnerProvider = testsRunnerProviderInfo.instantiateTestsRunnerProvider(); + this.startTime = System.currentTimeMillis(); + // Calculate approximate tests count by the previous similar testing session (if available) + if (previousSession != null) { + TestCasesCounter testCasesCounter = new TestCasesCounter(); + previousSession.getModelAccessor().getRootSuite().visit(testCasesCounter); + totalCounter = testCasesCounter.result; + } + ITestSuite rootTestSuite = previousSession != null ? previousSession.getModelAccessor().getRootSuite() : null; + this.modelManager = new TestModelManager(rootTestSuite, testsRunnerProviderInfo.isAllowedTestingTimeMeasurement()); + this.modelManager.addChangesListener(new ITestingSessionListener() { + + @Override + public void testingStarted() {} + + @Override + public void testingFinished() { + // This is necessary if totalCounter was -1 (tests count was unknown) + // or if tests count was estimated not accurately + totalCounter = currentCounter; + } + + @Override + public void exitTestSuite(ITestSuite testSuite) {} + + @Override + public void exitTestCase(ITestCase testCase) { + // Update testing session info (counters, flags) + Status testStatus = testCase.getStatus(); + statusCounters.put(testStatus, getCount(testStatus)+1); + ++currentCounter; + if (testStatus.isError()) + hasErrors = true; + } + + @Override + public void enterTestSuite(ITestSuite testSuite) {} + + @Override + public void enterTestCase(ITestCase testCase) {} + + @Override + public void childrenUpdate(ITestSuite parent) {} + }); + } + + /** + * Starts the processing of the test module output. + * + * @param inputStream test module output stream + */ + public void run(InputStream inputStream) { + modelManager.testingStarted(); + try { + testsRunnerProvider.run(modelManager, inputStream); + // If testing session was stopped, the status is set in stop() + if (!wasStopped()) { + double testingTime = getModelAccessor().getRootSuite().getTestingTime(); + statusMessage = MessageFormat.format(ModelMessages.TestingSession_finished_status, testingTime/1000.0); + } + } catch (TestingException e) { + // If testing session was stopped, the status is set in stop() + if (!wasStopped()) { + statusMessage = e.getLocalizedMessage(); + hasErrors = true; + } + } + finished = true; + modelManager.testingFinished(); + } + + @Override + public int getCurrentCounter() { + return currentCounter; + } + + @Override + public int getTotalCounter() { + return totalCounter; + } + + @Override + public int getCount(ITestItem.Status status) { + Integer counterValue = statusCounters.get(status); + return (counterValue == null) ? 0 : counterValue; + } + + @Override + public boolean hasErrors() { + return hasErrors; + } + + @Override + public boolean wasStopped() { + return wasStopped; + } + + @Override + public boolean isFinished() { + return finished; + } + + @Override + public ITestModelAccessor getModelAccessor() { + return modelManager; + } + + @Override + public ILaunch getLaunch() { + return launch; + } + + @Override + public TestsRunnerProviderInfo getTestsRunnerProviderInfo() { + return testsRunnerProviderInfo; + } + + @Override + public String getStatusMessage() { + return statusMessage; + } + + @Override + public String getName() { + String launchConfName = launch.getLaunchConfiguration().getName(); + String startTimeStr = DateFormat.getDateTimeInstance().format(new Date(startTime)); + return MessageFormat.format(ModelMessages.TestingSession_name_format, launchConfName, startTimeStr); + } + + @Override + public void stop() { + if (!launch.isTerminated() && launch.canTerminate()) { + try { + launch.terminate(); + wasStopped = true; + statusMessage = ModelMessages.TestingSession_stopped_status; + } catch (DebugException e) { + TestsRunnerPlugin.log(e); + } + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java new file mode 100644 index 00000000000..66bf252c6b5 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java @@ -0,0 +1,215 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.model; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProvidersManager; +import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; + +/** + * Manages all the testing sessions (creates, activates, stores history). + */ +public class TestingSessionsManager { + + /** Tests Runners Plug-ins Manager. */ + private TestsRunnerProvidersManager testsRunnersManager; + + /** Testing sessions history list (the first is the newest). */ + private LinkedList sessions = new LinkedList(); + + /** Currently active testing session. */ + private TestingSession activeSession; + + /** Listeners collection. */ + private List listeners = new ArrayList(); + + /** The size limit of the testing sessions history. */ + private int historySizeLimit = 10; + + public TestingSessionsManager(TestsRunnerProvidersManager testsRunnersManager) { + this.testsRunnersManager = testsRunnersManager; + } + + /** + * Tries to find the last testing session for the specified launch + * configuration and Tests Runner provide plug-in. + * + *

+ * Usually testing frameworks do not provide the information about tests + * hierarchy and total tests count before the testing is finished. So we try + * to reuse them from one the previous testing sessions that meets the + * requirements: + *

    + *
  • it should be for the same launch configuration; + *
  • it should be completed (finished and not stopped); + *
  • it should has the same tests runner; + *
+ * This function tries to find a such session. + *

+ * + * @param launchConfiguration required launch configuration + * @param testsRunnerProviderInfo required Tests Runner provide plug-in + * @return testing session or null if not found + */ + private TestingSession findActualPreviousSession(ILaunchConfiguration launchConfiguration, TestsRunnerProviderInfo testsRunnerProviderInfo) { + String testsRunnerName = testsRunnerProviderInfo.getName(); + for (TestingSession session : sessions) { + // Find the latest testing session that matches the next requirements: + // - it should be for the same launch configuration (should have the same parameters) + // - should be already terminated (to have complete tests hierarchy structure) + // - should not be stopped by user (the same as terminated) + // - should have the same tests runner + if (session != null) { + if (launchConfiguration.equals(session.getLaunch().getLaunchConfiguration()) + && session.isFinished() + && !session.wasStopped() + && session.getTestsRunnerProviderInfo().getName().equals(testsRunnerName)) { + return session; + } + } + } + return null; + } + + /** + * Creates a new testing session for the specified launch. + * + * @param launch launch + * @return new testing session + */ + public TestingSession newSession(ILaunch launch) throws CoreException { + TestsRunnerProviderInfo testsRunnerProviderInfo = testsRunnersManager.getTestsRunnerProviderInfo(launch.getLaunchConfiguration()); + TestingSession previousSession = findActualPreviousSession(launch.getLaunchConfiguration(), testsRunnerProviderInfo); + TestingSession newTestingSession = new TestingSession(launch, testsRunnerProviderInfo, previousSession); + sessions.addFirst(newTestingSession); + setActiveSession(newTestingSession); + truncateHistory(); + return newTestingSession; + } + + /** + * Returns the testing sessions history (the first is the newest). + * + * @return testing sessions list + */ + public List getSessions() { + return sessions; + } + + /** + * Rewrites the testing sessions history with the specified list. Truncates + * the history if necessary. + * + * @return testing sessions list + */ + public void setSessions(List newSessions) { + sessions.clear(); + for (ITestingSession newSession : newSessions) { + sessions.add((TestingSession) newSession); + } + truncateHistory(); + } + + /** + * Returns the testing sessions history size. + * + * @return history size + */ + public int getSessionsCount() { + return sessions.size(); + } + + /** + * Accesses the currently active testing session. + * + * @return testing session + */ + public ITestingSession getActiveSession() { + return activeSession; + } + + /** + * Sets the new active testing session. + * + * @param newActiveSession testing session + */ + public void setActiveSession(ITestingSession newActiveSession) { + if (activeSession != newActiveSession) { + activeSession = (TestingSession) newActiveSession; + // Notify listeners + for (ITestingSessionsManagerListener listener : listeners) { + listener.sessionActivated(activeSession); + } + } + } + + /** + * Adds the given listener to this registered listeners collection. + * Has no effect if an identical listener is already registered. + * + * @param listener the listener to add + */ + public void addListener(ITestingSessionsManagerListener listener) { + listeners.add(listener); + } + + /** + * Removes the given listener from registered listeners collection. + * Has no effect if the listener is not already registered. + * + * @param listener the listener to remove + */ + public void removeListener(ITestingSessionsManagerListener listener) { + listeners.remove(listener); + } + + /** + * Returns the size limit of the testing sessions history. + * + * @return history size limit + */ + public int getHistorySizeLimit() { + return historySizeLimit; + } + + /** + * Sets the size limit of the testing sessions history. + * + * @param historySizeLimit new history size limit + */ + public void setHistorySizeLimit(int historySizeLimit) { + this.historySizeLimit = historySizeLimit; + truncateHistory(); + } + + /** + * Truncates the history list if it is longer than size limit. + */ + private void truncateHistory() { + // The most frequently this method will be used to remove one element, so removeAll() is unnecessary here + while (sessions.size() > historySizeLimit) { + sessions.removeLast(); + } + // Handle the case when active testing session was removed from history due to truncation + if (!sessions.contains(activeSession)) { + ITestingSession newActiveSession = sessions.isEmpty() ? null : sessions.getFirst(); + setActiveSession(newActiveSession); + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java new file mode 100644 index 00000000000..bb1d058a4ec --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.launcher; + +import org.eclipse.cdt.launch.ui.CLaunchConfigurationTab; +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.launcher.ITestsLaunchConfigurationConstants; +import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + + +/** + * A launch configuration tab that displays and edits different testing options + * (e.g. Tests Runner provider plug-in). + *

+ * This class may be instantiated. This class is not intended to be subclassed. + *

+ * + * @noextend This class is not intended to be subclassed by clients. + */ +public class CTestingTab extends CLaunchConfigurationTab { + + /** + * Tab identifier used for ordering of tabs added using the + * org.eclipse.debug.ui.launchConfigurationTabs + * extension point. + */ + private static final String TAB_ID = "org.eclipse.cdt.testsrunner.testingTab"; //$NON-NLS-1$ + + private static final String TESTING_PROCESS_FACTORY_ID = "org.eclipse.cdt.testsrunner.TestingProcessFactory"; //$NON-NLS-1$ + + /** Shows the list of available Tests Runner provider plug-ins. */ + private Combo testsRunnerProviderCombo; + + /** Shows the description for the currently selected Tests Runner provider plug-in. */ + private Label testsRunnerProviderDescriptionLabel; + + @Override + public void createControl(Composite parent) { + Composite pageComposite = new Composite(parent, SWT.NONE); + GridLayout pageCompositeLayout = new GridLayout(2, false); + pageCompositeLayout.horizontalSpacing = 40; + pageComposite.setLayout(pageCompositeLayout); + + // Create a tests runner selector + new Label(pageComposite, SWT.NONE).setText(UILauncherMessages.CTestingTab_tests_runner_label); + testsRunnerProviderCombo = new Combo(pageComposite, SWT.READ_ONLY | SWT.DROP_DOWN); + testsRunnerProviderCombo.add(UILauncherMessages.CTestingTab_tests_runner_is_not_set); + testsRunnerProviderCombo.setData("0", null); //$NON-NLS-1$ + + // Add all the tests runners + for (TestsRunnerProviderInfo testsRunnerProviderInfo : TestsRunnerPlugin.getDefault().getTestsRunnerProvidersManager().getTestsRunnersProviderInfo()) { + testsRunnerProviderCombo.setData(Integer.toString(testsRunnerProviderCombo.getItemCount()), testsRunnerProviderInfo); + testsRunnerProviderCombo.add(testsRunnerProviderInfo.getName()); + } + + testsRunnerProviderCombo.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + testsRunnerProviderDescriptionLabel.setText(getCurrentTestsRunnerDescription()); + updateLaunchConfigurationDialog(); + } + }); + + // Create a tests runner description label + testsRunnerProviderDescriptionLabel = new Label(pageComposite, SWT.WRAP); + GridData testsRunnerProviderLabelGD = new GridData(GridData.FILL_BOTH); + testsRunnerProviderLabelGD.horizontalSpan = 2; + testsRunnerProviderLabelGD.horizontalAlignment = GridData.FILL; + testsRunnerProviderDescriptionLabel.setLayoutData(testsRunnerProviderLabelGD); + + GridData pageCompositeGD = new GridData(GridData.FILL_BOTH); + pageCompositeGD.horizontalAlignment = GridData.FILL; + pageCompositeGD.grabExcessHorizontalSpace = true; + pageComposite.setLayoutData(pageCompositeGD); + setControl(pageComposite); + } + + /** + * Returns the information for the currently selected Tests Runner provider + * plug-in. + * + * @return Tests Runner provide plug-in information + */ + private ITestsRunnerProviderInfo getCurrentTestsRunnerProviderInfo() { + return getTestsRunnerProviderInfo(testsRunnerProviderCombo.getSelectionIndex()); + } + + /** + * Returns the information for the Tests Runner provide plug-in specified by + * index. + * + * @param comboIndex index in combo widget + * @return Tests Runner provide plug-in information + */ + private ITestsRunnerProviderInfo getTestsRunnerProviderInfo(int comboIndex) { + return (ITestsRunnerProviderInfo)testsRunnerProviderCombo.getData(Integer.toString(comboIndex)); + } + + /** + * Returns the description for the currently selected Tests Runner provide + * plug-in. + * + * @return the description + */ + private String getCurrentTestsRunnerDescription() { + ITestsRunnerProviderInfo testsRunnerProvider = getCurrentTestsRunnerProviderInfo(); + if (testsRunnerProvider != null) { + return testsRunnerProvider.getDescription(); + } else { + return UILauncherMessages.CTestingTab_no_tests_runner_label; + } + } + + @Override + public boolean isValid(ILaunchConfiguration config) { + return getCurrentTestsRunnerProviderInfo() != null; + } + + @Override + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + config.setAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, (String) null); + config.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID, TESTING_PROCESS_FACTORY_ID); + } + + @Override + public void initializeFrom(ILaunchConfiguration configuration) { + try { + String testsRunnerId = configuration.getAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, (String) null); + int comboIndex = 0; + for (int i = 1; i < testsRunnerProviderCombo.getItemCount(); i++) { + if (getTestsRunnerProviderInfo(i).getId().equals(testsRunnerId)) { + comboIndex = i; + break; + } + } + testsRunnerProviderCombo.select(comboIndex); + + } catch (CoreException e) { + TestsRunnerPlugin.log(e); + } + } + + @Override + public void performApply(ILaunchConfigurationWorkingCopy configuration) { + ITestsRunnerProviderInfo testsRunnerProvider = getCurrentTestsRunnerProviderInfo(); + String testsRunnerProviderId = testsRunnerProvider != null ? testsRunnerProvider.getId() : null; + configuration.setAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, testsRunnerProviderId); + configuration.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID, TESTING_PROCESS_FACTORY_ID); + } + + @Override + public String getId() { + return TAB_ID; + } + + @Override + public String getName() { + return UILauncherMessages.CTestingTab_tab_name; + } + + @Override + public String getErrorMessage() { + String m = super.getErrorMessage(); + if (m == null) { + if (getCurrentTestsRunnerProviderInfo() == null) { + return UILauncherMessages.CTestingTab_no_tests_runner_error; + } + } + return m; + } + + @Override + public Image getImage() { + return TestsRunnerPlugin.createAutoImage("obj16/test_notrun.gif"); //$NON-NLS-1$ + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java new file mode 100644 index 00000000000..77a9d44cd22 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.launcher; + +import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.debug.ui.ILaunchConfigurationTab; + + +/** + * Represents an empty tab group. Actual tabs are added via the + * org.eclipse.debug.ui.launchConfigurationTabs extension point. + */ +public class EmptyConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup { + + @Override + public void createTabs(ILaunchConfigurationDialog dialog, String mode) { + setTabs(new ILaunchConfigurationTab[0]); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java new file mode 100644 index 00000000000..8e75b59f54b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.launcher; + +import org.eclipse.osgi.util.NLS; + +public class UILauncherMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.ui.launcher.UILauncherMessages"; //$NON-NLS-1$ + public static String CTestingTab_no_tests_runner_error; + public static String CTestingTab_no_tests_runner_label; + public static String CTestingTab_tab_name; + public static String CTestingTab_tests_runner_is_not_set; + public static String CTestingTab_tests_runner_label; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, UILauncherMessages.class); + } + + private UILauncherMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties new file mode 100644 index 00000000000..752755e5f7d --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +CTestingTab_no_tests_runner_error=Tests runner is not selected +CTestingTab_no_tests_runner_label=Select a tests runner... +CTestingTab_tab_name=C/C++ Testing +CTestingTab_tests_runner_is_not_set= +CTestingTab_tests_runner_label=Tests Runner diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java new file mode 100644 index 00000000000..4f3f8d910e8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import java.text.MessageFormat; + + +/** + * Shows a simple tests count statics information (run/error/failed). + */ +public class CounterPanel extends Composite { + + /** Testing session to show statistics for. */ + private ITestingSession testingSession; + + /** Widget showing the failed tests count. */ + private Label failedCounterLabel; + + /** Widget showing the error tests count. */ + private Label abortedCounterLabel; + + /** Widget showing the run tests count. */ + private Label currentCounterLabel; + + /** + * Shows whether there were skipped tests. It is used to force layout of the + * counter widgets after skipped tests are appeared. + */ + private boolean hasSkipped; + + private final Image errorIcon = TestsRunnerPlugin.createAutoImage("ovr16/failed_counter.gif"); //$NON-NLS-1$ + private final Image failureIcon = TestsRunnerPlugin.createAutoImage("ovr16/aborted_counter.gif"); //$NON-NLS-1$ + + + public CounterPanel(Composite parent, ITestingSession testingSession) { + super(parent, SWT.WRAP); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 9; + gridLayout.makeColumnsEqualWidth = false; + gridLayout.marginWidth = 0; + setLayout(gridLayout); + + currentCounterLabel = createLabel(UIViewMessages.CounterPanel_tests_run, null); + abortedCounterLabel = createLabel(UIViewMessages.CounterPanel_tests_erred, errorIcon); + failedCounterLabel = createLabel(UIViewMessages.CounterPanel_tests_failed, failureIcon); + setTestingSession(testingSession); + } + + /** + * Creates counter label widget. + * + * @param name widget text prefix + * @param image widget image or null + * @return created label + */ + private Label createLabel(String name, Image image) { + Label label = new Label(this, SWT.NONE); + if (image != null) { + image.setBackground(label.getBackground()); + label.setImage(image); + } + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + label = new Label(this, SWT.NONE); + label.setText(name); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + Label value = new Label(this, SWT.READ_ONLY); + value.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING)); + return value; + } + + /** + * Sets the testing session to show information about. + * + * @param testingSession testing session (null is not acceptable) + */ + public void setTestingSession(ITestingSession testingSession) { + this.testingSession = testingSession; + this.hasSkipped = testingSession.getCount(ITestItem.Status.Skipped) != 0; + updateInfoFromSession(); + } + + /** + * Updates the information on the panel from the currently set testing + * session. + */ + public void updateInfoFromSession() { + setFailedCounter(testingSession.getCount(ITestItem.Status.Failed)); + setAbortedCounter(testingSession.getCount(ITestItem.Status.Aborted)); + setCurrentCounter(testingSession.getCurrentCounter(), testingSession.getCount(ITestItem.Status.Skipped)); + redraw(); + } + + /** + * Sets a new value for the failed tests counter. + * + * @param newValue new counter value + */ + private void setFailedCounter(int newValue) { + failedCounterLabel.setText(Integer.toString(newValue)); + } + + /** + * Sets a new value for the error tests counter. + * + * @param newValue new counter value + */ + private void setAbortedCounter(int newValue) { + abortedCounterLabel.setText(Integer.toString(newValue)); + } + + /** + * Sets a new value for the run tests counter. + * + * @param currentValue new counter value + * @param skippedValue skipped tests counter + */ + private void setCurrentCounter(int currentValue, int skippedValue) { + if (!hasSkipped && skippedValue != 0) { + layout(); + } + String runString = (skippedValue == 0) + ? Integer.toString(currentValue) + : MessageFormat.format(UIViewMessages.CounterPanel_tests_skipped, currentValue, skippedValue); + currentCounterLabel.setText(runString); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java new file mode 100644 index 00000000000..9787a5bb5b4 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestModelAccessor; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.debug.core.ILaunch; + +/** + * Represents a simple testing session which is used for UI when there is no + * "real" testing sessions to show (e.g. when there was no launched testing + * session or when all of them were cleared). + */ +public class DummyUISession implements ITestingSession { + + @Override + public int getCurrentCounter() { + return 0; + } + + @Override + public int getTotalCounter() { + return 0; + } + + @Override + public int getCount(ITestItem.Status status) { + return 0; + } + + @Override + public boolean hasErrors() { + return false; + } + + @Override + public boolean wasStopped() { + return false; + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public ITestModelAccessor getModelAccessor() { + return null; + } + + @Override + public ILaunch getLaunch() { + return null; + } + + @Override + public ITestsRunnerProviderInfo getTestsRunnerProviderInfo() { + return null; + } + + @Override + public String getStatusMessage() { + return ""; //$NON-NLS-1$ + } + + @Override + public String getName() { + return ""; //$NON-NLS-1$ + } + + @Override + public void stop() { + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java new file mode 100644 index 00000000000..db0aa21e9b8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java @@ -0,0 +1,573 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import java.io.File; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; + +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.CopySelectedMessagesAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.OpenInEditorAction; +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestCase; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestLocation; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.eclipse.cdt.testsrunner.model.ITestMessage.Level; +import org.eclipse.cdt.testsrunner.model.ITestSuite; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.IOpenListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.ActionFactory; + + +/** + * Shows the messages for the currently selected items in tests hierarchy (test + * suites or test cases). + */ +public class MessagesViewer { + + /** + * Enumeration of all possible message filter actions by level. + */ + public enum LevelFilter { + Info(ISharedImages.IMG_OBJS_INFO_TSK, ITestMessage.Level.Info, ITestMessage.Level.Message), + Warning(ISharedImages.IMG_OBJS_WARN_TSK, ITestMessage.Level.Warning), + Error(ISharedImages.IMG_OBJS_ERROR_TSK, ITestMessage.Level.Error, ITestMessage.Level.FatalError, ITestMessage.Level.Exception); + + private String imageId; + private ITestMessage.Level [] includedLevels; + + LevelFilter(String imageId, ITestMessage.Level... includedLevels) { + this.imageId = imageId; + this.includedLevels = includedLevels; + } + + /** + * The shared image ID corresponding to the message level filter action. + * + * @return shared image ID + */ + public String getImageId() { + return imageId; + } + + /** + * The message levels that should be shown if current message level + * filter action is set. + * + * @return array of message levels + */ + public ITestMessage.Level [] getLevels() { + return includedLevels; + } + + /** + * Checks whether the specified message level should be shown if current + * message level filter action is set. + * + * @param messageLevel message level to search + * @return true if found + */ + public boolean isIncluded(ITestMessage.Level messageLevel) { + for (ITestMessage.Level currLevel : includedLevels) { + if (currLevel.equals(messageLevel)) { + return true; + } + } + return false; + } + } + + /** + * The content provider for the test messages viewer. + */ + private class MessagesContentProvider implements IStructuredContentProvider { + + /** + * Utility class: recursively collects all the messages of the specified + * test item. + */ + class MessagesCollector implements IModelVisitor { + + /** Collected test messages. */ + Collection collectedTestMessages; + + /** + * Specifies whether gathering should be done. It is used to skip + * the messages of the passed tests if they should not be shown. + */ + boolean collect = true; + + MessagesCollector(Collection testMessages) { + this.collectedTestMessages = testMessages; + } + + @Override + public void visit(ITestMessage testMessage) { + if (collect) { + collectedTestMessages.add(testMessage); + } + } + + @Override + public void visit(ITestCase testCase) { + collect = !showFailedOnly || testCase.getStatus().isError(); + } + + @Override + public void visit(ITestSuite testSuite) {} + + @Override + public void leave(ITestSuite testSuite) {} + + @Override + public void leave(ITestCase testCase) {} + + @Override + public void leave(ITestMessage testMessage) {} + } + + /** Test messages to show in the viewer. */ + ITestMessage[] testMessages; + + @Override + public void inputChanged(Viewer v, Object oldInput, Object newInput) { + if (newInput != null) { + collectMessages((ITestItem[]) newInput); + } else { + testMessages = new ITestMessage[0]; + } + } + + @Override + public void dispose() { + } + + @Override + public Object[] getElements(Object parent) { + return testMessages; + } + + /** + * Creates a messages set with a custom comparator. It is used for the + * ordered messages showing. + * + * @return set to store the test messages + */ + private TreeSet createMessagesSet() { + return new TreeSet(new Comparator() { + + @Override + public int compare(ITestMessage message1, ITestMessage message2) { + // Compare messages by location + ITestLocation location1 = message1.getLocation(); + ITestLocation location2 = message2.getLocation(); + + if (location1 != null && location2 != null) { + // Compare by file name + String file1 = location1.getFile(); + String file2 = location2.getFile(); + int fileResult = file1.compareTo(file2); + if (fileResult != 0) { + return fileResult; + } else { + // Compare by line number + int line1 = location1.getLine(); + int line2 = location2.getLine(); + if (line1 < line2) { + return -1; + + } else if (line1 > line2) { + return 1; + } + } + + } else if (location1 == null && location2 != null) { + return -1; + + } else if (location1 != null && location2 == null) { + return 1; + } + + // Compare by message text + String text1 = message1.getText(); + String text2 = message2.getText(); + return text1.compareTo(text2); + } + }); + } + + /** + * Creates a list to store the test messages. It is used for the + * unordered messages showing. + * + * @return list to store the test messages + */ + private ArrayList createMessagesList() { + return new ArrayList(); + } + + /** + * Creates a collection to store the test messages depending on whether + * ordering is required. + * + * @return collection to store the test messages + */ + private Collection createMessagesCollection() { + return orderingMode ? createMessagesSet() : createMessagesList(); + } + + /** + * Run messages collecting for the specified test items. + * + * @param testItems test items array + */ + private void collectMessages(ITestItem[] testItems) { + Collection testMessagesCollection = createMessagesCollection(); + for (ITestItem testItem : testItems) { + testItem.visit(new MessagesCollector(testMessagesCollection)); + } + testMessages = testMessagesCollection.toArray(new ITestMessage[testMessagesCollection.size()]); + } + } + + /** + * The label provider for the test messages viewer. + */ + private class MessagesLabelProvider extends LabelProvider implements ITableLabelProvider { + + /** + * Returns the full (file path) or short (file name only) file path view + * depending on the filter set. + * + * @param location test object location + * @return file path + */ + private String getLocationFile(ITestLocation location) { + String filePath = location.getFile(); + if (showFileNameOnly) { + return new File(filePath).getName(); + } else { + return filePath; + } + } + + @Override + public String getColumnText(Object obj, int index) { + ITestMessage message = (ITestMessage)obj; + ITestLocation location = message.getLocation(); + String locationString = ""; //$NON-NLS-1$ + if (location != null) { + locationString = MessageFormat.format( + UIViewMessages.MessagesViewer_location_format, + new Object[] { getLocationFile(location), location.getLine() } + ); + } + return MessageFormat.format(UIViewMessages.MessagesViewer_message_format, + locationString, message.getLevel(), message.getText() + ); + } + + @Override + public Image getColumnImage(Object obj, int index) { + return getImage(obj); + } + + @Override + public Image getImage(Object obj) { + Level level = ((ITestMessage)obj).getLevel(); + String imageId = ISharedImages.IMG_OBJ_ELEMENT; + for (LevelFilter levelFilter : LevelFilter.values()) { + if (levelFilter.isIncluded(level)) { + imageId = levelFilter.getImageId(); + break; + } + } + return PlatformUI.getWorkbench().getSharedImages().getImage(imageId); + } + } + + /** + * Filters the required test messages by level. + */ + private class MessageLevelFilter extends ViewerFilter { + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + return acceptedMessageLevels.contains(((ITestMessage)element).getLevel()); + } + } + + + /** Main widget. */ + private TableViewer tableViewer; + + private IViewSite viewSite; + + // Context menu actions + private OpenInEditorAction openInEditorAction; + private Action copyAction; + + /** Specifies whether only messages for failed tests should be shown. */ + private boolean showFailedOnly = false; + + /** + * Specifies whether only file names should be shown (instead of full file + * paths). + */ + private boolean showFileNameOnly = false; + + /** The set of message level to show the messages with. */ + private Set acceptedMessageLevels = new HashSet(); + + /** Specifies whether test messages ordering is on or off. */ + private boolean orderingMode = false; + + + public MessagesViewer(Composite parent, + TestingSessionsManager sessionsManager, IWorkbench workbench, + IViewSite viewSite, Clipboard clipboard) { + this.viewSite = viewSite; + tableViewer = new TableViewer(parent, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL); + tableViewer.setLabelProvider(new MessagesLabelProvider()); + tableViewer.setContentProvider(new MessagesContentProvider()); + tableViewer.addFilter(new MessageLevelFilter()); + initContextMenu(viewSite, sessionsManager, workbench, clipboard); + tableViewer.addOpenListener(new IOpenListener() { + @Override + public void open(OpenEvent event) { + openInEditorAction.run(); + } + }); + } + + /** + * Initializes the viewer context menu. + * + * @param viewSite view + * @param sessionsManager testing sessions manager + * @param workbench workbench + * @param clipboard clipboard + */ + private void initContextMenu(IViewSite viewSite, + TestingSessionsManager sessionsManager, IWorkbench workbench, + Clipboard clipboard) { + openInEditorAction = new OpenInEditorAction(tableViewer, sessionsManager, workbench); + copyAction = new CopySelectedMessagesAction(tableViewer, clipboard); + + MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ + menuMgr.addMenuListener(new IMenuListener() { + @Override + public void menuAboutToShow(IMenuManager manager) { + handleMenuAboutToShow(manager); + } + }); + viewSite.registerContextMenu(menuMgr, tableViewer); + Menu menu = menuMgr.createContextMenu(tableViewer.getTable()); + tableViewer.getTable().setMenu(menu); + + menuMgr.add(openInEditorAction); + menuMgr.add(copyAction); + configureCopy(); + } + + /** + * Configures the view copy action which should be run on CTRL+C. We have to + * track widget focus to select the actual action because we have a few + * widgets that should provide copy action (at least tests hierarchy viewer + * and messages viewer). + */ + private void configureCopy() { + getTableViewer().getTable().addFocusListener(new FocusListener() { + IAction viewCopyHandler; + + @Override + public void focusLost(FocusEvent e) { + if (viewCopyHandler != null) { + switchTo(viewCopyHandler); + } + } + + @Override + public void focusGained(FocusEvent e) { + switchTo(copyAction); + } + + private void switchTo(IAction copyAction) { + IActionBars actionBars = viewSite.getActionBars(); + viewCopyHandler = actionBars.getGlobalActionHandler(ActionFactory.COPY.getId()); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction); + actionBars.updateActionBars(); + } + }); + } + + /** + * Handles the context menu showing. + * + * @param manager context menu manager + */ + private void handleMenuAboutToShow(IMenuManager manager) { + ISelection selection = tableViewer.getSelection(); + openInEditorAction.setEnabled(!selection.isEmpty()); + copyAction.setEnabled(!selection.isEmpty()); + } + + /** + * Provides access to the main widget of the messages viewer. + * + * @return main widget of the messages viewer + */ + public TableViewer getTableViewer() { + return tableViewer; + } + + /** + * Sets the test items for which the messages should be shown. + * + * @param testItems test items array + */ + public void showItemsMessages(ITestItem[] testItems) { + tableViewer.setInput(testItems); + } + + /** + * Forces the messages recollecting. It is used after message filters + * change. + */ + private void forceRecollectMessages() { + // NOTE: Set input again makes content provider to recollect messages (with filters applied) + tableViewer.setInput(tableViewer.getInput()); + } + + /** + * Returns whether the messages only for the failed tests should be shown. + * + * @return filter state + */ + public boolean getShowFailedOnly() { + return showFailedOnly; + } + + /** + * Sets whether the messages only for the failed tests should be shown. + * + * @param showFailedOnly new filter state + */ + public void setShowFailedOnly(boolean showFailedOnly) { + if (this.showFailedOnly != showFailedOnly) { + this.showFailedOnly = showFailedOnly; + forceRecollectMessages(); + } + } + + /** + * Returns whether short or long view for file paths should be shown. + * + * @return filter state + */ + public boolean getShowFileNameOnly() { + return showFileNameOnly; + } + + /** + * Sets whether short or long view for file paths should be shown. + * + * @param showFileNameOnly new filter state + */ + public void setShowFileNameOnly(boolean showFileNameOnly) { + if (this.showFileNameOnly != showFileNameOnly) { + this.showFileNameOnly = showFileNameOnly; + forceRecollectMessages(); + } + } + + /** + * Returns whether test messages should be ordered by location. + * + * @return messages ordering state + */ + public boolean getOrderingMode() { + return orderingMode; + } + + /** + * Sets whether test messages should be ordered by location. + * + * @param orderingMode new messages ordering state + */ + public void setOrderingMode(boolean orderingMode) { + if (this.orderingMode != orderingMode) { + this.orderingMode = orderingMode; + forceRecollectMessages(); + } + } + + /** + * Adds the filter message level filters by the message filter action level. + * + * @param levelFilter message filter action level + * @param refresh specifies whether viewer should be refreshed after filter + * update (small optimization: avoid many updates on initialization) + */ + public void addLevelFilter(LevelFilter levelFilter, boolean refresh) { + for (ITestMessage.Level level : levelFilter.getLevels()) { + acceptedMessageLevels.add(level); + } + if (refresh) { + tableViewer.refresh(); + } + } + + /** + * Removed the filter message level filters by the message filter action + * level. + * + * @param levelFilter message filter action level + */ + public void removeLevelFilter(LevelFilter levelFilter) { + for (ITestMessage.Level level : levelFilter.getLevels()) { + acceptedMessageLevels.remove(level); + } + tableViewer.refresh(); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java new file mode 100644 index 00000000000..dc1c0044209 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + +/** + * A progress bar with a red/green indication for testing success or failure. + */ +public class ProgressBar extends Canvas { + + /** Default bar width */ + private static final int DEFAULT_WIDTH = 160; + + /** Default bar height */ + private static final int DEFAULT_HEIGHT = 18; + + /** Testing session to show progress bar for. */ + private ITestingSession testingSession; + + /** Current bar width. */ + private int colorBarWidth; + + /** The bar color when everything is OK (no tests failed and no testing errors). */ + private Color okColor; + + /** The bar color when there are tests failed and or testing errors. */ + private Color failureColor; + + /** The bar color when the testing session was stopped by user. */ + private Color stoppedColor; + + + public ProgressBar(Composite parent, ITestingSession testingSession) { + super(parent, SWT.NONE); + + addControlListener(new ControlAdapter() { + @Override + public void controlResized(ControlEvent e) { + updateInfoFromSession(); + } + }); + addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + paint(e); + } + }); + + // Manage progress bar colors + Display display = parent.getDisplay(); + failureColor = new Color(display, 159, 63, 63); + okColor = new Color(display, 95, 191, 95); + stoppedColor = new Color(display, 120, 120, 120); + addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + failureColor.dispose(); + okColor.dispose(); + stoppedColor.dispose(); + } + }); + setTestingSession(testingSession); + } + + /** + * Sets the testing session to show information about. + * + * @param testingSession testing session (null is not acceptable) + */ + public void setTestingSession(ITestingSession testingSession) { + this.testingSession = testingSession; + updateInfoFromSession(); + } + + /** + * Updates the progress from the currently set testing session. + */ + public void updateInfoFromSession() { + recalculateColorBarWidth(); + redraw(); + } + + /** + * Sets the color of the progress bar depending on the testing session. + * + * @param gc gc + */ + private void setStatusColor(GC gc) { + if (testingSession.wasStopped()) + gc.setBackground(stoppedColor); + else if (testingSession.hasErrors()) + gc.setBackground(failureColor); + else + gc.setBackground(okColor); + } + + /** + * Calculate the width of the progress rectangle in a widget. + * + * @note If total tests count is known it is used to determine width of the + * progress rectangle. If it isn't the width of progress rectangle is set to + * the half of a widget. + */ + private void recalculateColorBarWidth() { + Rectangle r = getClientArea(); + int newColorBarWidth; + if (testingSession.getTotalCounter() > 0) { + newColorBarWidth = testingSession.getCurrentCounter()*(r.width-2)/testingSession.getTotalCounter(); + } else { + newColorBarWidth = testingSession.getCurrentCounter() > 0 ? (r.width-2)/2 : (testingSession.isFinished() ? r.width-2 : 0); + } + colorBarWidth = Math.max(0, newColorBarWidth); + } + + /** + * Draws the widget border + */ + private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) { + gc.setForeground(topleft); + gc.drawLine(x, y, x+w-1, y); + gc.drawLine(x, y, x, y+h-1); + + gc.setForeground(bottomright); + gc.drawLine(x+w, y, x+w, y+h); + gc.drawLine(x, y+h, x+w, y+h); + } + + /** + * Handles paint event and redraws the widget if necessary. + * + * @param event paint event + */ + private void paint(PaintEvent event) { + GC gc = event.gc; + Display disp = getDisplay(); + + Rectangle rect = getClientArea(); + gc.fillRectangle(rect); + drawBevelRect(gc, rect.x, rect.y, rect.width-1, rect.height-1, + disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW), + disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); + + setStatusColor(gc); + colorBarWidth = Math.min(rect.width-2, colorBarWidth); + gc.fillRectangle(1, 1, colorBarWidth, rect.height-2); + } + + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + checkWidget(); + Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT); + if (wHint != SWT.DEFAULT) { + size.x = wHint; + } + if (hHint != SWT.DEFAULT) { + size.y = hHint; + } + return size; + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java new file mode 100644 index 00000000000..eb8e65cb4ac --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; + +/** + * A statistics panel that compounds counter panel and red/green progress bar. + * Depending on orientation it may layout them vertically or horizontally. + */ +public class ProgressCountPanel extends Composite { + + /** Child widget: counter panel. */ + private CounterPanel counterPanel; + + /** Child widget: red/green progress bar */ + private ProgressBar progressBar; + + /** + * Dummy session is used when there is no "real" testing sessions to show + * (e.g. when there was no launched testing session or when all of them were + * cleared). + */ + private DummyUISession dummyUISession = new DummyUISession(); + + + public ProgressCountPanel(Composite parent, ResultsView.Orientation currOrientation) { + super(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + setLayout(layout); + setPanelOrientation(currOrientation); + + counterPanel = new CounterPanel(this, dummyUISession); + counterPanel.setLayoutData( + new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); + progressBar = new ProgressBar(this, dummyUISession); + progressBar.setLayoutData( + new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); + + // Data for parent (view's) layout + setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); + } + + /** + * Sets the testing session to show information about. + * + * @param testingSession testing session or null to set default empty + * session + */ + public void setTestingSession(ITestingSession testingSession) { + ITestingSession newSession = (testingSession != null) ? testingSession : dummyUISession; + counterPanel.setTestingSession(newSession); + progressBar.setTestingSession(newSession); + } + + /** + * Updates the information on the panel from the currently set testing + * session. + */ + public void updateInfoFromSession() { + counterPanel.updateInfoFromSession(); + progressBar.updateInfoFromSession(); + } + + /** + * Sets the widget orientation. + * + * @param orientation new widget orientation (vertical or horizontal; auto + * is not supported) + */ + public void setPanelOrientation(ResultsView.Orientation orientation) { + ((GridLayout)getLayout()).numColumns = (orientation == ResultsView.Orientation.Horizontal) ? 2 : 1; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java new file mode 100644 index 00000000000..50c8d94c8b8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java @@ -0,0 +1,245 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import java.util.Iterator; + +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.internal.ui.view.MessagesViewer.LevelFilter; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.MessageLevelFilterAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.MessagesOrderingAction; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.custom.ViewForm; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.IWorkbench; + +/** + * The main widget of testing results view. It compounds tests hierarchy and + * messages viewer. Depending on orientation it may layout them vertically or + * horizontally. + */ +public class ResultsPanel { + + /** Parent for the child widgets (messages & tests hierarchy viewer). */ + private SashForm sashForm; + + /** Child widget: messages viewer. */ + private MessagesViewer messagesViewer; + + /** Child widget: tests hierarchy viewer. */ + private TestsHierarchyViewer testsHierarchyViewer; + + // Persistence tags + static final String TAG_WEIGHT0 = "weight0"; //$NON-NLS-1$ + static final String TAG_WEIGHT1 = "weight1"; //$NON-NLS-1$ + static final String TAG_MESSAGES_ORDERING_ACTION = "messagesOrderingAction"; //$NON-NLS-1$ + static final String TAG_ERROR_FILTER_ACTION = "errorFilterAction"; //$NON-NLS-1$ + static final String TAG_WARNING_FILTER_ACTION = "warningFilterAction"; //$NON-NLS-1$ + static final String TAG_INFO_FILTER_ACTION = "infoFilterAction"; //$NON-NLS-1$ + + // Messages Viewer actions + Action messagesOrderingAction; + Action errorFilterAction; + Action warningFilterAction; + Action infoFilterAction; + + + public ResultsPanel(Composite parent, TestingSessionsManager sessionsManager, IWorkbench workbench, IViewSite site, Clipboard clipboard) { + sashForm = new SashForm(parent, SWT.VERTICAL); + + // Configure tests hierarchy viewer + ViewForm top = new ViewForm(sashForm, SWT.NONE); + Composite empty = new Composite(top, SWT.NONE); + empty.setLayout(new Layout() { + @Override + protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { + return new Point(1, 1); // (0, 0) does not work with super-intelligent ViewForm + } + @Override + protected void layout(Composite composite, boolean flushCache) {} + }); + top.setTopLeft(empty); // makes ViewForm draw the horizontal separator line ... + testsHierarchyViewer = new TestsHierarchyViewer(top, site, clipboard); + top.setContent(testsHierarchyViewer.getTreeViewer().getControl()); + + // Configure test messages viewer + ViewForm bottom = new ViewForm(sashForm, SWT.NONE); + messagesViewer = new MessagesViewer(bottom, sessionsManager, workbench, site, clipboard); + Composite topLeftPanel = new Composite(bottom, SWT.NONE); + RowLayout topLeftPanelLayout = new RowLayout(SWT.HORIZONTAL); + topLeftPanelLayout.spacing = 0; + topLeftPanelLayout.center = true; + topLeftPanelLayout.marginBottom = topLeftPanelLayout.marginLeft = topLeftPanelLayout.marginRight = topLeftPanelLayout.marginTop = 0; + topLeftPanel.setLayout(topLeftPanelLayout); + ToolBar leftMessagesToolBar = new ToolBar(topLeftPanel, SWT.FLAT | SWT.WRAP); + ToolBarManager leftMessagesToolBarManager = new ToolBarManager(leftMessagesToolBar); + messagesOrderingAction = new MessagesOrderingAction(messagesViewer); + leftMessagesToolBarManager.add(messagesOrderingAction); + leftMessagesToolBarManager.update(true); + CLabel label = new CLabel(topLeftPanel, SWT.NONE); + label.setText(UIViewMessages.MessagesPanel_label); + bottom.setTopLeft(topLeftPanel); + ToolBar rightMessagesToolBar = new ToolBar(bottom, SWT.FLAT | SWT.WRAP); + ToolBarManager rightMessagesToolBarManager = new ToolBarManager(rightMessagesToolBar); + errorFilterAction = new MessageLevelFilterAction(messagesViewer, LevelFilter.Error, true); + warningFilterAction = new MessageLevelFilterAction(messagesViewer, LevelFilter.Warning, true); + infoFilterAction = new MessageLevelFilterAction(messagesViewer, LevelFilter.Info, false); + rightMessagesToolBarManager.add(errorFilterAction); + rightMessagesToolBarManager.add(warningFilterAction); + rightMessagesToolBarManager.add(infoFilterAction); + rightMessagesToolBarManager.update(true); + bottom.setTopCenter(rightMessagesToolBar); + bottom.setContent(messagesViewer.getTableViewer().getControl()); + + sashForm.setWeights(new int[]{50, 50}); + + testsHierarchyViewer.getTreeViewer().addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + handleTestItemSelected(); + } + }); + + // Initialize default value + setShowFailedOnly(false); + + // Data for parent (view's) layout + sashForm.setLayoutData(new GridData(GridData.FILL_BOTH)); + } + + /** + * Provides access to the tests hierarchy viewer. + * + * @return tests hierarchy viewer + */ + public TestsHierarchyViewer getTestsHierarchyViewer() { + return testsHierarchyViewer; + } + + /** + * Provides access to the messages viewer. + * + * @return messages viewer + */ + public MessagesViewer getMessagesViewer() { + return messagesViewer; + } + + /** + * Handles selection change in tests hierarchy viewer and updates the + * content of the messages viewer to show the messages for the selected + * items. + */ + private void handleTestItemSelected() { + IStructuredSelection selection = (IStructuredSelection)testsHierarchyViewer.getTreeViewer().getSelection(); + ITestItem[] testItems = new ITestItem[selection.size()]; + int index = 0; + for (Iterator it = selection.iterator(); it.hasNext();) { + testItems[index] = (ITestItem)it.next(); + ++index; + } + messagesViewer.showItemsMessages(testItems); + } + + /** + * Sets the widget orientation. + * + * @param orientation new widget orientation (vertical or horizontal; auto + * is not supported) + */ + public void setPanelOrientation(ResultsView.Orientation orientation) { + sashForm.setOrientation(orientation == ResultsView.Orientation.Horizontal ? SWT.HORIZONTAL : SWT.VERTICAL); + } + + /** + * Returns whether only failed tests (and messages for them) should be + * shown. + * + * @return filter state + */ + public boolean getShowFailedOnly() { + return messagesViewer.getShowFailedOnly(); + } + + /** + * Sets whether only failed tests (and messages for them) should be shown. + * + * @param showFailedOnly new filter state + */ + public void setShowFailedOnly(boolean showFailedOnly) { + testsHierarchyViewer.setShowFailedOnly(showFailedOnly); + messagesViewer.setShowFailedOnly(showFailedOnly); + } + + /** + * Restores the value of the checkable action. + * + * @param memento previously saved state to restore the action value from + * @param key tag name that is used to restore the value + * @param action action to restore + */ + private void restoreActionChecked(IMemento memento, String key, Action action) { + Boolean checked = memento.getBoolean(key); + if (checked != null) { + action.setChecked(checked); + action.run(); + } + } + + /** + * Restores the state of the widget. + * + * @param memento previously saved state + */ + public void restoreState(IMemento memento) { + Integer weight0 = memento.getInteger(TAG_WEIGHT0); + Integer weight1 = memento.getInteger(TAG_WEIGHT1); + if (weight0 != null && weight1 != null) { + sashForm.setWeights(new int[] {weight0, weight1}); + } + restoreActionChecked(memento, TAG_MESSAGES_ORDERING_ACTION, messagesOrderingAction); + restoreActionChecked(memento, TAG_ERROR_FILTER_ACTION, errorFilterAction); + restoreActionChecked(memento, TAG_WARNING_FILTER_ACTION, warningFilterAction); + restoreActionChecked(memento, TAG_INFO_FILTER_ACTION, infoFilterAction); + } + + /** + * Saves the state of the widget. + * + * @param memento where to save the state + */ + public void saveState(IMemento memento) { + int[] weights = sashForm.getWeights(); + memento.putInteger(TAG_WEIGHT0, weights[0]); + memento.putInteger(TAG_WEIGHT1, weights[1]); + memento.putBoolean(TAG_MESSAGES_ORDERING_ACTION, messagesOrderingAction.isChecked()); + memento.putBoolean(TAG_ERROR_FILTER_ACTION, errorFilterAction.isChecked()); + memento.putBoolean(TAG_WARNING_FILTER_ACTION, warningFilterAction.isChecked()); + memento.putBoolean(TAG_INFO_FILTER_ACTION, infoFilterAction.isChecked()); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java new file mode 100644 index 00000000000..585cf84e80b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java @@ -0,0 +1,366 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.HistoryDropDownAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RerunAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ScrollLockAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowFailedOnlyAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowFileNameOnlyAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowNextFailureAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowPreviousFailureAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowTestsInHierarchyAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowTimeAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.StopAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ToggleOrientationAction; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.part.ViewPart; + +/** + * Represents a view part showing the testing results (count statistics, + * red/green bar, tests hierarchy and test messages). + */ +public class ResultsView extends ViewPart { + + /** + * Represents view orientation + * + * @note Auto state may be not acceptable for some methods (see + * their comments for details). + */ + public enum Orientation { + Horizontal, + Vertical, + Auto, + } + + /** View parent. */ + private Composite parent; + + /** Child widget: statistics viewer. */ + private ProgressCountPanel progressCountPanel; + + /** Tests hierarchy and message viewer. */ + private ResultsPanel resultsPanel; + + /** User interface updater instance. */ + private UIUpdater uiUpdater; + + /** The reference to the testing sessions manager instance. */ + private TestingSessionsManager sessionsManager; + + /** Shows whether the results view was disposed. */ + private boolean isDisposed = false; + + // Toolbar & view menu actions + private Action nextAction; + private Action previousAction; + private Action rerunAction; + private Action stopAction; + private ToggleOrientationAction[] toggleOrientationActions; + private Action historyAction; + private Action showFailedOnly; + private Action showTestsInHierarchyAction; + private Action showTimeAction; + private Action scrollLockAction; + private Action showFileNameOnlyAction; + + /** + * The current orientation preference (Horizontal, Vertical, Auto). + */ + private Orientation orientation = Orientation.Auto; + + /** + * The current view orientation (Horizontal or Vertical). + */ + private Orientation currentOrientation; + + /** + * Previously saved state. It is used to store the same state if the view + * was not opened. + */ + private IMemento memento; + + // Persistence tags + static final String TAG_ORIENTATION = "orientation"; //$NON-NLS-1$ + static final String TAG_SHOW_FAILED_ONLY = "showFailedOnly"; //$NON-NLS-1$ + static final String TAG_SHOW_TESTS_IN_HIERARCHY = "showTestsInHierarchy"; //$NON-NLS-1$ + static final String TAG_SHOW_TIME = "showTime"; //$NON-NLS-1$ + static final String TAG_SCROLL_LOCK = "scrollLock"; //$NON-NLS-1$ + static final String TAG_SHOW_FILE_NAME_ONLY_ACTION = "showFileNameOnly"; //$NON-NLS-1$ + static final String TAG_HISTORY_SIZE = "history_size"; //$NON-NLS-1$ + + + @Override + public void createPartControl(Composite parent) { + sessionsManager = TestsRunnerPlugin.getDefault().getTestingSessionsManager(); + IWorkbench workbench = TestsRunnerPlugin.getDefault().getWorkbench(); + Clipboard clipboard = new Clipboard(parent.getDisplay()); + + this.parent = parent; + GridLayout gridLayout = new GridLayout(); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + parent.setLayout(gridLayout); + currentOrientation = getActualOrientation(); + + progressCountPanel = new ProgressCountPanel(parent, currentOrientation); + resultsPanel = new ResultsPanel(parent, sessionsManager, workbench, getViewSite(), clipboard); + uiUpdater = new UIUpdater(this, resultsPanel.getTestsHierarchyViewer(), progressCountPanel, sessionsManager); + configureActionsBars(); + + parent.addControlListener(new ControlListener() { + @Override + public void controlMoved(ControlEvent e) { + } + @Override + public void controlResized(ControlEvent e) { + computeOrientation(); + } + }); + + restoreState(memento); + uiUpdater.reapplyActiveSession(); + } + + @Override + public void setFocus() { + resultsPanel.getTestsHierarchyViewer().getTreeViewer().getControl().setFocus(); + } + + /** + * Configures the view tool bar and menu. + */ + private void configureActionsBars() { + IActionBars actionBars = getViewSite().getActionBars(); + + // Create common action + toggleOrientationActions = new ToggleOrientationAction[] { + new ToggleOrientationAction(this, Orientation.Vertical), + new ToggleOrientationAction(this, Orientation.Horizontal), + new ToggleOrientationAction(this, Orientation.Auto), + }; + + nextAction = new ShowNextFailureAction(resultsPanel.getTestsHierarchyViewer()); + nextAction.setEnabled(false); + actionBars.setGlobalActionHandler(ActionFactory.NEXT.getId(), nextAction); + + previousAction = new ShowPreviousFailureAction(resultsPanel.getTestsHierarchyViewer()); + previousAction.setEnabled(false); + actionBars.setGlobalActionHandler(ActionFactory.PREVIOUS.getId(), previousAction); + + showFailedOnly = new ShowFailedOnlyAction(resultsPanel); + showTestsInHierarchyAction = new ShowTestsInHierarchyAction(resultsPanel.getTestsHierarchyViewer()); + showTimeAction = new ShowTimeAction(resultsPanel.getTestsHierarchyViewer()); + scrollLockAction = new ScrollLockAction(uiUpdater); + showFileNameOnlyAction = new ShowFileNameOnlyAction(resultsPanel.getMessagesViewer()); + rerunAction = new RerunAction(sessionsManager); + rerunAction.setEnabled(false); + stopAction = new StopAction(sessionsManager); + stopAction.setEnabled(false); + + historyAction = new HistoryDropDownAction(sessionsManager, parent.getShell()); + + // Configure toolbar + IToolBarManager toolBar = actionBars.getToolBarManager(); + toolBar.add(nextAction); + toolBar.add(previousAction); + toolBar.add(showFailedOnly); + toolBar.add(scrollLockAction); + toolBar.add(new Separator()); + toolBar.add(rerunAction); + toolBar.add(stopAction); + toolBar.add(historyAction); + + // Configure view menu + IMenuManager viewMenu = actionBars.getMenuManager(); + viewMenu.add(showTestsInHierarchyAction); + viewMenu.add(showTimeAction); + viewMenu.add(new Separator()); + MenuManager layoutSubMenu = new MenuManager(UIViewMessages.ResultsView_layout_menu_text); + for (int i = 0; i < toggleOrientationActions.length; ++i) { + layoutSubMenu.add(toggleOrientationActions[i]); + } + viewMenu.add(layoutSubMenu); + viewMenu.add(new Separator()); + viewMenu.add(showFailedOnly); + viewMenu.add(showFileNameOnlyAction); + } + + @Override + public void dispose() { + isDisposed = true; + if (uiUpdater != null) { + uiUpdater.dispose(); + } + } + + /** + * Changes the view orientation + * + * @param orientation new view orientation (Horizontal, Vertical, Auto) + */ + public void setOrientation(Orientation orientation) { + this.orientation = orientation; + computeOrientation(); + } + + /** + * Checks whether actual orientation is changed and changes orientation of + * the child widgets. + */ + private void computeOrientation() { + Orientation newActualOrientation = getActualOrientation(); + if (newActualOrientation != currentOrientation) { + currentOrientation = newActualOrientation; + progressCountPanel.setPanelOrientation(currentOrientation); + resultsPanel.setPanelOrientation(currentOrientation); + for (int i = 0; i < toggleOrientationActions.length; ++i) { + toggleOrientationActions[i].setChecked(orientation == toggleOrientationActions[i].getOrientation()); + } + parent.layout(); + } + } + + /** + * Recalculates actual view orientation depending on the specified by user + * orientation value and current view size. + * + * @param orientation by user specified orientation + * @return actual orientation + */ + private Orientation getActualOrientation() { + switch (orientation) { + case Horizontal: + case Vertical: + return orientation; + case Auto: + Point size = parent.getSize(); + return (size.x > size.y) ? Orientation.Horizontal : Orientation.Vertical; + } + return null; + } + + /** + * Updates view actions state from the active session. + */ + public void updateActionsFromSession() { + ITestingSession session = sessionsManager.getActiveSession(); + boolean hasErrors = session != null && session.hasErrors(); + previousAction.setEnabled(hasErrors); + nextAction.setEnabled(hasErrors); + rerunAction.setEnabled(session != null && session.isFinished()); + stopAction.setEnabled(session != null && !session.isFinished()); + } + + /** + * Changes the view caption. + * + * @param message new view caption + */ + public void setCaption(String message) { + setContentDescription(message); + } + + @Override + public void init(IViewSite site, IMemento memento) throws PartInitException { + super.init(site, memento); + this.memento = memento; + } + + /** + * Restores the value of the checkable action. + * + * @param memento previously saved state to restore the action value from + * @param key tag name that is used to restore the value + * @param action action to restore + */ + private void restoreActionChecked(IMemento memento, String key, Action action) { + Boolean checked = memento.getBoolean(key); + if (checked != null) { + action.setChecked(checked); + action.run(); + } + } + + /** + * Restores the state of the view. + * + * @param memento previously saved state + */ + private void restoreState(IMemento memento) { + if (memento != null) { + Integer orientationIndex = memento.getInteger(TAG_ORIENTATION); + if (orientationIndex != null) { + setOrientation(Orientation.values()[orientationIndex]); + } + resultsPanel.restoreState(memento); + restoreActionChecked(memento, TAG_SHOW_FAILED_ONLY, showFailedOnly); + restoreActionChecked(memento, TAG_SHOW_TESTS_IN_HIERARCHY, showTestsInHierarchyAction); + restoreActionChecked(memento, TAG_SHOW_TIME, showTimeAction); + restoreActionChecked(memento, TAG_SCROLL_LOCK, scrollLockAction); + restoreActionChecked(memento, TAG_SHOW_FILE_NAME_ONLY_ACTION, showFileNameOnlyAction); + Integer historySize = memento.getInteger(TAG_HISTORY_SIZE); + if (historySize != null) { + sessionsManager.setHistorySizeLimit(historySize); + } + } + } + + @Override + public void saveState(IMemento memento) { + //Keep the old state; + if (parent == null) { + if (this.memento != null) { + memento.putMemento(this.memento); + } + return; + } + + memento.putInteger(TAG_ORIENTATION, orientation.ordinal()); + resultsPanel.saveState(memento); + memento.putBoolean(TAG_SHOW_FAILED_ONLY, showFailedOnly.isChecked()); + memento.putBoolean(TAG_SHOW_TESTS_IN_HIERARCHY, showTestsInHierarchyAction.isChecked()); + memento.putBoolean(TAG_SHOW_TIME, showTimeAction.isChecked()); + memento.putBoolean(TAG_SCROLL_LOCK, scrollLockAction.isChecked()); + memento.putBoolean(TAG_SHOW_FILE_NAME_ONLY_ACTION, showFileNameOnlyAction.isChecked()); + memento.putInteger(TAG_HISTORY_SIZE, sessionsManager.getHistorySizeLimit()); + } + + /** + * Returns whether the view was disposed. + * + * @return true if the view was disposed + */ + public boolean isDisposed() { + return isDisposed; + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java new file mode 100644 index 00000000000..512754435a7 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.testsrunner.model.ITestItem; + +/** + * The utilities collection to work with the test paths for items in test + * hierarchy. + */ +public class TestPathUtils { + + /** + * The delimiter between parts of serialized test path. Should not be met in + * test paths names. + */ + private static final String TEST_PATH_PART_DELIMITER = "\n"; //$NON-NLS-1$ + + /** The delimiter between parts of human readable test path. */ + private static final String TEST_PATH_DELIMITER = "."; //$NON-NLS-1$ + + /** + * Returns the human readable path to the item in test hierarchy (e.g. + * MySuite.MyInnerSuite.MyTest1). + * + * @param testItem test item (test suite or test case) + * + * @return path to test item + */ + public static String getTestItemPath(ITestItem testItem) { + StringBuilder itemPath = new StringBuilder(); + List parentItems = new ArrayList(); + while (testItem != null) { + parentItems.add(testItem); + testItem = testItem.getParent(); + } + if (!parentItems.isEmpty()) { + for (int i = parentItems.size()-2/* exclude unnamed root test suite */; i >= 0; --i) { + itemPath.append(parentItems.get(i).getName()); + if (i != 0) { + itemPath.append(TEST_PATH_DELIMITER); + } + } + } + return itemPath.toString(); + } + + /** + * Unpack the paths from the string list. + * + * @param testPaths packed test paths + * @return array of test paths + * + * @see packTestPaths() + */ + public static String[][] unpackTestPaths(String[] testPaths) { + String [][] result = new String[testPaths.length][]; + for (int i = 0; i < result.length; i++) { + result[i] = testPaths[i].split(TEST_PATH_PART_DELIMITER); + } + return result; + } + + /** + * Pack the paths to specified test items to string list. + * + * @param testItems test items to pack + * @return string list + * + * @see unpackTestPaths() + */ + public static String[] packTestPaths(ITestItem[] testItems) { + String [] result = new String[testItems.length]; + List testPath = new ArrayList(); + + for (int itemIdx = 0; itemIdx < testItems.length; itemIdx++) { + // Collect test path parts (in reverse order) + testPath.clear(); + ITestItem item = testItems[itemIdx]; + while (item != null) { + // Exclude root test suite + if (item.getParent()!= null) { + testPath.add(item.getName()); + } + item = item.getParent(); + } + // Join path parts into the only string + StringBuilder sb = new StringBuilder(); + boolean needDelimiter = false; + for (int pathPartIdx = testPath.size()-1; pathPartIdx >= 0; pathPartIdx--) { + if (needDelimiter) { + sb.append(TEST_PATH_PART_DELIMITER); + } else { + needDelimiter = true; + } + sb.append(testPath.get(pathPartIdx)); + } + result[itemIdx] = sb.toString(); + } + return result; + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java new file mode 100644 index 00000000000..117a7b3beec --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java @@ -0,0 +1,554 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.internal.ui.viewsupport.ColoringLabelProvider; +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.CopySelectedTestsAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RedebugSelectedAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RelaunchSelectedAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RerunSelectedAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.TestsHierarchyCollapseAllAction; +import org.eclipse.cdt.testsrunner.internal.ui.view.actions.TestsHierarchyExpandAllAction; +import org.eclipse.cdt.testsrunner.model.IModelVisitor; +import org.eclipse.cdt.testsrunner.model.ITestCase; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.eclipse.cdt.testsrunner.model.ITestSuite; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StyledCellLabelProvider; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.actions.ActionFactory; + +/** + * Shows the tests hierarchy in a flat or hierarchical view. + */ +public class TestsHierarchyViewer { + + /** + * The content provider for the tests hierarchy viewer. + */ + private class TestTreeContentProvider implements ITreeContentProvider { + + /** + * Utility class: recursively collects all the test cases of the + * specified test item. + * + * It is used for flat view of tests hierarchy. + */ + private class TestCasesCollector implements IModelVisitor { + + public List testCases = new ArrayList(); + + @Override + public void visit(ITestCase testCase) { + testCases.add(testCase); + } + + @Override + public void visit(ITestMessage testMessage) {} + @Override + public void visit(ITestSuite testSuite) {} + @Override + public void leave(ITestSuite testSuite) {} + @Override + public void leave(ITestCase testCase) {} + @Override + public void leave(ITestMessage testMessage) {} + } + + @Override + public Object[] getChildren(Object parentElement) { + return ((ITestItem) parentElement).getChildren(); + } + + @Override + public Object[] getElements(Object rootTestSuite) { + if (showTestsHierarchy) { + return getChildren(rootTestSuite); + } else { + TestCasesCollector testCasesCollector = new TestCasesCollector(); + ((ITestItem)rootTestSuite).visit(testCasesCollector); + return testCasesCollector.testCases.toArray(); + } + } + + @Override + public Object getParent(Object object) { + return ((ITestItem) object).getParent(); + } + + @Override + public boolean hasChildren(Object object) { + return ((ITestItem) object).hasChildren(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} + + @Override + public void dispose() {} + } + + /** + * The label provider for the tests hierarchy viewer. + */ + private class TestLabelProvider extends LabelProvider implements IStyledLabelProvider { + + /** Images for the test cases with the different statuses. */ + private Map testCaseImages = new HashMap(); + { + testCaseImages.put(ITestItem.Status.NotRun, TestsRunnerPlugin.createAutoImage("obj16/test_notrun.gif")); //$NON-NLS-1$ + testCaseImages.put(ITestItem.Status.Skipped, TestsRunnerPlugin.createAutoImage("obj16/test_skipped.gif")); //$NON-NLS-1$ + testCaseImages.put(ITestItem.Status.Passed, TestsRunnerPlugin.createAutoImage("obj16/test_passed.gif")); //$NON-NLS-1$ + testCaseImages.put(ITestItem.Status.Failed, TestsRunnerPlugin.createAutoImage("obj16/test_failed.gif")); //$NON-NLS-1$ + testCaseImages.put(ITestItem.Status.Aborted, TestsRunnerPlugin.createAutoImage("obj16/test_aborted.gif")); //$NON-NLS-1$ + } + + /** Running test case image (overrides the test case status image). */ + private Image testCaseRunImage = TestsRunnerPlugin.createAutoImage("obj16/test_run.gif"); //$NON-NLS-1$ + + /** Images for the test suites with the different statuses. */ + private Map testSuiteImages = new HashMap(); + { + // NOTE: There is no skipped-icon for test suite, but it seems it is not a problem + testSuiteImages.put(ITestItem.Status.NotRun, TestsRunnerPlugin.createAutoImage("obj16/tsuite_notrun.gif")); //$NON-NLS-1$ + testSuiteImages.put(ITestItem.Status.Skipped, TestsRunnerPlugin.createAutoImage("obj16/tsuite_notrun.gif")); //$NON-NLS-1$ + testSuiteImages.put(ITestItem.Status.Passed, TestsRunnerPlugin.createAutoImage("obj16/tsuite_passed.gif")); //$NON-NLS-1$ + testSuiteImages.put(ITestItem.Status.Failed, TestsRunnerPlugin.createAutoImage("obj16/tsuite_failed.gif")); //$NON-NLS-1$ + testSuiteImages.put(ITestItem.Status.Aborted, TestsRunnerPlugin.createAutoImage("obj16/tsuite_aborted.gif")); //$NON-NLS-1$ + } + + /** Running test suite image (overrides the test suite status image). */ + private Image testSuiteRunImage = TestsRunnerPlugin.createAutoImage("obj16/tsuite_run.gif"); //$NON-NLS-1$ + + /** Small optimization: the last test item cache */ + private ITestItem lastTestItemCache = null; + + /** Small optimization: test path for the last test item is cache */ + private String lastTestItemPathCache = null; + + + @Override + public Image getImage(Object element) { + Map imagesMap = null; + Image runImage = null; + if (element instanceof ITestCase) { + imagesMap = testCaseImages; + runImage = testCaseRunImage; + + } else if (element instanceof ITestSuite) { + imagesMap = testSuiteImages; + runImage = testSuiteRunImage; + } + if (imagesMap != null) { + ITestItem testItem = (ITestItem)element; + if (testingSession.getModelAccessor().isCurrentlyRunning(testItem)) { + return runImage; + } + return imagesMap.get(testItem.getStatus()); + } + + return null; + } + + @Override + public String getText(Object element) { + ITestItem testItem = (ITestItem)element; + StringBuilder sb = new StringBuilder(); + sb.append(testItem.getName()); + if (!showTestsHierarchy) { + appendTestItemPath(sb, testItem); + } + if (showTime) { + sb.append(getTestingTimeString(element)); + } + return sb.toString(); + } + + @Override + public StyledString getStyledText(Object element) { + ITestItem testItem = (ITestItem)element; + StringBuilder labelBuf = new StringBuilder(); + labelBuf.append(testItem.getName()); + StyledString name = new StyledString(labelBuf.toString()); + if (!showTestsHierarchy) { + appendTestItemPath(labelBuf, testItem); + name = StyledCellLabelProvider.styleDecoratedString(labelBuf.toString(), StyledString.QUALIFIER_STYLER, name); + } + if (showTime) { + String time = getTestingTimeString(element); + labelBuf.append(time); + name = StyledCellLabelProvider.styleDecoratedString(labelBuf.toString(), StyledString.COUNTER_STYLER, name); + } + return name; + } + + /** + * Appends path to the parent of the specified test item. Also + * implements caching of the last path (cause the test item parent is + * often the same). + * + * @param sb string builder to append test item path to + * @param testItem specified test item + */ + private void appendTestItemPath(StringBuilder sb, ITestItem testItem) { + ITestSuite testItemParent = testItem.getParent(); + if (lastTestItemCache != testItemParent) { + lastTestItemCache = testItemParent; + lastTestItemPathCache = TestPathUtils.getTestItemPath(lastTestItemCache); + } + sb.append(MessageFormat.format( + UIViewMessages.TestsHierarchyViewer_test_path_format, + new Object[] { lastTestItemPathCache } + )); + } + + /** + * Returns the execution time suffix for the test item. + * + * @param element test item + * @return execution time suffix + */ + private String getTestingTimeString(Object element) { + return (element instanceof ITestItem) + ? MessageFormat.format(UIViewMessages.TestsHierarchyViewer_test_time_format, Double.toString(((ITestItem)element).getTestingTime()/1000.0)) + : ""; //$NON-NLS-1$ + } + + } + + /** + * Filters passed test cases and test suites. + */ + private class FailedOnlyFilter extends ViewerFilter { + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + return ((ITestItem)element).getStatus().isError(); + } + } + + /** Testing session to show hierarchy of. */ + private ITestingSession testingSession; + + /** Main widget. */ + private TreeViewer treeViewer; + + /** Specifies whether test items execution time should be shown in hierarchy. */ + private boolean showTime = true; + + /** Specifies whether tests hierarchy should be shown in flat or hierarchical view. */ + private boolean showTestsHierarchy = true; + + /** Failed only tree filter instance. Created on first demand. */ + private FailedOnlyFilter failedOnlyFilter = null; + + /** System clipboard access to provide copy operations. */ + private Clipboard clipboard; + + // Context menu actions + private Action expandAllAction; + private Action collapseAllAction; + private Action copyAction; + private RelaunchSelectedAction rerunAction; + private RelaunchSelectedAction redebugAction; + + + public TestsHierarchyViewer(Composite parent, IViewSite viewSite, Clipboard clipboard) { + this.clipboard = clipboard; + treeViewer = new TreeViewer(parent, SWT.V_SCROLL | SWT.MULTI); + treeViewer.setContentProvider(new TestTreeContentProvider()); + treeViewer.setLabelProvider(new ColoringLabelProvider(new TestLabelProvider())); + initContextMenu(viewSite); + } + + /** + * Initializes the viewer context menu. + * + * @param viewSite view + */ + private void initContextMenu(IViewSite viewSite) { + expandAllAction = new TestsHierarchyExpandAllAction(treeViewer); + collapseAllAction = new TestsHierarchyCollapseAllAction(treeViewer); + copyAction = new CopySelectedTestsAction(treeViewer, clipboard); + rerunAction = new RerunSelectedAction(testingSession, treeViewer); + redebugAction = new RedebugSelectedAction(testingSession, treeViewer); + + MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ + menuMgr.addMenuListener(new IMenuListener() { + @Override + public void menuAboutToShow(IMenuManager manager) { + handleMenuAboutToShow(manager); + } + }); + viewSite.registerContextMenu(menuMgr, treeViewer); + Menu menu = menuMgr.createContextMenu(treeViewer.getTree()); + treeViewer.getTree().setMenu(menu); + + menuMgr.add(copyAction); + menuMgr.add(new Separator()); + menuMgr.add(rerunAction); + menuMgr.add(redebugAction); + menuMgr.add(new Separator()); + menuMgr.add(expandAllAction); + menuMgr.add(collapseAllAction); + + IActionBars actionBars = viewSite.getActionBars(); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction); + actionBars.updateActionBars(); + } + + /** + * Handles the context menu showing. + * + * @param manager context menu manager + */ + private void handleMenuAboutToShow(IMenuManager manager) { + IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection(); + boolean isRelaunchEnabledForSelection = !selection.isEmpty() && + (testingSession.getTestsRunnerProviderInfo().isAllowedMultipleTestFilter() || (selection.size() == 1)); + rerunAction.setEnabled(isRelaunchEnabledForSelection); + rerunAction.setTestingSession(testingSession); + redebugAction.setEnabled(isRelaunchEnabledForSelection); + redebugAction.setTestingSession(testingSession); + copyAction.setEnabled(!selection.isEmpty()); + + boolean hasAnything = treeViewer.getInput() != null; + expandAllAction.setEnabled(hasAnything); + collapseAllAction.setEnabled(hasAnything); + } + + /** + * Sets the testing session to show. + * + * @param testingSession testing session or null to set default empty + * session + */ + public void setTestingSession(ITestingSession testingSession) { + this.testingSession = testingSession; + treeViewer.setInput(testingSession != null ? testingSession.getModelAccessor().getRootSuite() : null); + } + + /** + * Provides access to the main widget of the tests hierarchy viewer. + * + * @return main widget of the tests hierarchy viewer + */ + public TreeViewer getTreeViewer() { + return treeViewer; + } + + /** + * Move the selection to the next failed test case. + */ + public void showNextFailure() { + showFailure(true); + } + + /** + * Move the selection to the previous failed test case. + */ + public void showPreviousFailure() { + showFailure(false); + } + + /** + * Common implementation for movement the selection to the next or previous + * failed test case. + * + * @param next true if the next failed test case should be selected and false otherwise + */ + private void showFailure(boolean next) { + IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection(); + ITestItem selected = (ITestItem) selection.getFirstElement(); + ITestItem failedItem; + + if (selected == null) { + ITestItem rootSuite = (ITestItem)treeViewer.getInput(); + // For next element we should also check its children, for previous shouldn't. + failedItem = findFailedImpl(rootSuite, null, next, next); + } else { + // For next element we should also check its children, for previous shouldn't. + failedItem = findFailedImpl(selected.getParent(), selected, next, next); + } + + if (failedItem != null) + getTreeViewer().setSelection(new StructuredSelection(failedItem), true); + } + + /** + * Returns the next or previous failed test case relatively to the + * currItem that should be a child of parentItem. + * If the such item was not found through the children, it steps up to the + * parent and continues search. + * + * @param parentItem parent test item to the current one + * @param currItem current item search should be started from or null if + * there is no any + * @param next true if the next failed test case should be looked for and + * false otherwise + * @param checkCurrentChild specifies whether the search should be also + * through the children for the current item + * @return found item or null + */ + private ITestItem findFailedImpl(ITestItem parentItem, ITestItem currItem, boolean next, boolean checkCurrentChild) { + ITestItem result = findFailedChild(parentItem, currItem, next, checkCurrentChild); + if (result != null) { + return result; + } + // Nothing found at this level - try to step up + ITestSuite grandParentItem = parentItem.getParent(); + if (grandParentItem != null) { + return findFailedImpl(grandParentItem, parentItem, next, false); + } + return null; + } + + /** + * Returns the next or previous failed test case relatively to the + * currItem that should be a child of parentItem. + * Note that unlike findFailedImpl() this method search only + * through the children items. + * + * @param parentItem parent test item to the current one + * @param currItem current item search should be started from or null if + * there is no any + * @param next true if the next failed test case should be looked for and + * false otherwise + * @param checkCurrentChild specifies whether the search should be also + * through the children for the current item + * @return found item or null + */ + private ITestItem findFailedChild(ITestItem parentItem, ITestItem currItem, boolean next, boolean checkCurrentChild) { + ITestItem[] children = parentItem.getChildren(); + boolean doSearch = (currItem == null); + int increment = next ? 1 : -1; + int startIndex = next ? 0 : children.length-1; + int endIndex = next ? children.length : -1; + for (int index = startIndex; index != endIndex; index += increment) { + ITestItem item = children[index]; + // Check element + if (doSearch) { + if (item instanceof ITestCase && item.getStatus().isError()) { + return item; + } + } + // If children of current element should be checked we should enable search here (if necessary) + if (checkCurrentChild && item == currItem) { + doSearch = true; + } + // Search element's children + if (doSearch) { + ITestItem result = findFailedChild(item, null, next, checkCurrentChild); + if (result != null) { + return result; + } + } + // If children of current element should NOT be checked we should enable search here + if (!checkCurrentChild && item == currItem) { + doSearch = true; + } + } + return null; + } + + /** + * Returns whether test items execution time should be shown in tests + * hierarchy. + * + * @return true if time should be shown and false otherwise + */ + public boolean showTime() { + return showTime; + } + + /** + * Sets whether test items execution time should be shown in tests + * hierarchy. Updates tests hierarchy viewer if the view is changed. + * + * @param showTime true if time is shown and false otherwise + */ + public void setShowTime(boolean showTime) { + if (this.showTime != showTime) { + this.showTime = showTime; + getTreeViewer().refresh(); + } + } + + /** + * Sets whether only failed tests should be shown. + * + * @param showFailedOnly new filter state + */ + public void setShowFailedOnly(boolean showFailedOnly) { + // Create filter on first demand + if (failedOnlyFilter == null) { + failedOnlyFilter = new FailedOnlyFilter(); + } + if (showFailedOnly) { + getTreeViewer().addFilter(failedOnlyFilter); + } else { + getTreeViewer().removeFilter(failedOnlyFilter); + } + } + + /** + * Returns whether tests hierarchy should be shown in flat or hierarchical + * mode. + * + * @return tests hierarchy view mode + */ + public boolean showTestsHierarchy() { + return showTestsHierarchy; + } + + /** + * Sets whether tests hierarchy should be shown in flat or hierarchical + * mode. Updates tests hierarchy viewer if the view is changed. + * + * @param showTestsHierarchy true if tests hierarchy is shown in + * hierarchical mode and false otherwise + */ + public void setShowTestsHierarchy(boolean showTestsHierarchy) { + if (this.showTestsHierarchy != showTestsHierarchy) { + this.showTestsHierarchy = showTestsHierarchy; + getTreeViewer().refresh(); + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java new file mode 100644 index 00000000000..a6738e0d7e8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java @@ -0,0 +1,517 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import java.text.MessageFormat; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.testsrunner.internal.model.ITestingSessionsManagerListener; +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.cdt.testsrunner.model.ITestingSessionListener; +import org.eclipse.cdt.testsrunner.model.ITestCase; +import org.eclipse.cdt.testsrunner.model.ITestSuite; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.progress.UIJob; + +/** + * Tracks and collects the changes in active testing session and updates the UI + * periodically. It allows to significantly improve the UI performance. + */ +public class UIUpdater { + + /** Access to the results showing view. */ + private ResultsView resultsView; + + /** Access to the tests hierarchy showing widget. */ + private TestsHierarchyViewer testsHierarchyViewer; + + /** Access to the statistics showing widget. */ + private ProgressCountPanel progressCountPanel; + + /** Listener for the changes in active testing session. */ + private ITestingSessionListener sessionListener; + + /** + * Specifies whether tests hierarchy scrolling should be done during the + * testing process. + */ + private boolean autoScroll = true; + + /** Access to the testing sessions manager. */ + private TestingSessionsManager sessionsManager; + + /** Listener to handle active testing session change. */ + private TestingSessionsManagerListener sessionsManagerListener; + + /** Reference to the active testing session. */ + ITestingSession testingSession; + + /** Storage for the UI changes that should be done on update. */ + UIChangesCache uiChangesCache = new UIChangesCache(); + + /** A job that makes an UI update periodically. */ + UpdateUIJob updateUIJob = null; + + /** Time interval over which the UI should be updated. */ + private static final int REFRESH_INTERVAL = 200; + + + /** + * Storage for the UI changes that should be done on update. + */ + private class UIChangesCache { + + /** + * Specifies whether Progress Counter Panel should be updated during the + * next UI update. + */ + private boolean needProgressCountPanelUpdate; + + /** + * Specifies whether view actions should be updated during the next UI + * update. + */ + private boolean needActionsUpdate; + + /** + * A test item which path should be shown as a view caption during the + * next UI update. + */ + private ITestItem testItemForNewViewCaption; + + /** + * Set of tree objects on which refresh() should be called + * during the next UI update. + */ + private Set treeItemsToRefresh = new HashSet(); + + /** + * Set of tree objects on which update() should be called + * during the next UI update. + */ + private Set treeItemsToUpdate = new HashSet(); + + /** Tree object that should be revealed during the next UI update. */ + private Object treeItemToReveal; + + /** Map of tree objects that should be expanded or collapsed to their new states. */ + private Map treeItemsToExpand = new LinkedHashMap(); + + + UIChangesCache() { + resetChanges(); + } + + /** + * Schedules the Progress Counter Panel update during the next UI update. + */ + public void scheduleProgressCountPanelUpdate() { + synchronized (this) { + needProgressCountPanelUpdate = true; + } + } + + /** + * Schedules the view actions update during the next UI update. + */ + public void scheduleActionsUpdate() { + synchronized (this) { + needActionsUpdate = true; + } + } + + /** + * Schedules the view caption update to the path to specified test item + * during the next UI update. + * + * @param testItem specified test item + */ + public void scheduleViewCaptionChange(ITestItem testItem) { + synchronized (this) { + testItemForNewViewCaption = testItem; + } + } + + /** + * Schedules the update() call for the specified tree + * object during the next UI update. + * + * @param item tree object to update + */ + public void scheduleTreeItemUpdate(Object item) { + synchronized (this) { + treeItemsToUpdate.add(item); + } + } + + /** + * Schedules the revealing of the specified tree object. Overrides + * the previously specified tree object to reveal (if any). + * + * @param item tree object to reveal + */ + public void scheduleTreeItemReveal(Object item) { + synchronized (this) { + treeItemToReveal = item; + } + } + + /** + * Schedules the expanding or collapsing of the specified tree object. + * Overrides the previous state for the same tree object (if any). + * + * @param item tree object to expand or collapse + * @param expandedState true if the node is expanded, and false if + * collapsed + */ + public void scheduleTreeItemExpand(Object item, boolean expandedState) { + synchronized (this) { + treeItemsToExpand.put(item, expandedState); + } + } + + /** + * Schedules the refresh() call for the specified tree + * object during the next UI update. + * + * @param item tree object to refresh + */ + public void scheduleTreeItemRefresh(Object item) { + synchronized (this) { + treeItemsToRefresh.add(item); + } + } + + + /** + * Apply any scheduled changes to UI. + */ + public void applyChanges() { + synchronized (this) { + TreeViewer treeViewer = testsHierarchyViewer.getTreeViewer(); + // View statistics widgets update + if (needProgressCountPanelUpdate) { + progressCountPanel.updateInfoFromSession(); + } + // View actions update + if (needActionsUpdate) { + resultsView.updateActionsFromSession(); + } + // View caption update + if (testItemForNewViewCaption != null) { + resultsView.setCaption( + MessageFormat.format( + UIViewMessages.UIUpdater_view_caption_format, + testItemForNewViewCaption.getName(), + TestPathUtils.getTestItemPath(testItemForNewViewCaption.getParent()) + ) + ); + } + // Tree view update + if (!treeItemsToRefresh.isEmpty()) { + for (Object item : treeItemsToRefresh) { + treeViewer.refresh(item, false); + } + } + if (!treeItemsToUpdate.isEmpty()) { + treeViewer.update(treeItemsToUpdate.toArray(), null); + } + if (treeItemToReveal != null) { + treeViewer.reveal(treeItemToReveal); + } + if (!treeItemsToExpand.isEmpty()) { + for (Map.Entry entry : treeItemsToExpand.entrySet()) { + treeViewer.setExpandedState(entry.getKey(), entry.getValue()); + } + } + // All changes are applied, remove them + resetChangesImpl(); + } + } + + /** + * Reset all the scheduled changes to UI. + */ + public void resetChanges() { + synchronized (this) { + resetChangesImpl(); + } + } + + /** + * Reset all the scheduled changes to UI. Note, this method is not + * synchronized so it should be used carefully + */ + private void resetChangesImpl() { + needProgressCountPanelUpdate = false; + needActionsUpdate = false; + testItemForNewViewCaption = null; + treeItemsToUpdate.clear(); + treeItemToReveal = null; + treeItemsToExpand.clear(); + } + } + + + /** + * A job that makes an UI update periodically. + */ + private class UpdateUIJob extends UIJob { + + /** Controls whether the job should be scheduled again. */ + private boolean isRunning = true; + + public UpdateUIJob() { + super(UIViewMessages.UIUpdater_update_ui_job); + setSystem(true); + } + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + if (!resultsView.isDisposed()) { + uiChangesCache.applyChanges(); + scheduleSelf(); + } + return Status.OK_STATUS; + } + + /** + * Schedule self for running after time interval. + */ + public void scheduleSelf() { + schedule(REFRESH_INTERVAL); + } + + /** + * Sets the flag that prevents planning this job again. + */ + public void stop() { + isRunning = false; + } + + @Override + public boolean shouldSchedule() { + return isRunning; + } + + } + + + /** + * Listener for the changes in active testing session. + */ + private class SessionListener implements ITestingSessionListener { + + /** + * Common implementation for test case and test suite entering. + * + * @param testItem test case or test suite + */ + private void enterTestItem(ITestItem testItem) { + uiChangesCache.scheduleViewCaptionChange(testItem); + uiChangesCache.scheduleTreeItemUpdate(testItem); + if (autoScroll) { + uiChangesCache.scheduleTreeItemReveal(testItem); + } + } + + @Override + public void enterTestSuite(ITestSuite testSuite) { + enterTestItem(testSuite); + } + + @Override + public void exitTestSuite(ITestSuite testSuite) { + uiChangesCache.scheduleTreeItemUpdate(testSuite); + if (autoScroll) { + uiChangesCache.scheduleTreeItemExpand(testSuite, false); + } + } + + @Override + public void enterTestCase(ITestCase testCase) { + enterTestItem(testCase); + } + + @Override + public void exitTestCase(ITestCase testCase) { + uiChangesCache.scheduleActionsUpdate(); + uiChangesCache.scheduleProgressCountPanelUpdate(); + uiChangesCache.scheduleTreeItemUpdate(testCase); + } + + @Override + public void childrenUpdate(ITestSuite parent) { + uiChangesCache.scheduleTreeItemRefresh(parent); + } + + @Override + public void testingStarted() { + resultsView.updateActionsFromSession(); + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + resultsView.setCaption(testingSession.getStatusMessage()); + progressCountPanel.updateInfoFromSession(); + testsHierarchyViewer.getTreeViewer().refresh(); + } + }); + startUpdateUIJob(); + } + + @Override + public void testingFinished() { + stopUpdateUIJob(); + resultsView.updateActionsFromSession(); + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + uiChangesCache.applyChanges(); + resultsView.setCaption(testingSession.getStatusMessage()); + progressCountPanel.updateInfoFromSession(); + testsHierarchyViewer.getTreeViewer().refresh(); + testsHierarchyViewer.getTreeViewer().collapseAll(); + testsHierarchyViewer.getTreeViewer().expandToLevel(2); + } + }); + } + } + + + /** + * Listener to handle active testing session change. + */ + private class TestingSessionsManagerListener implements ITestingSessionsManagerListener { + + @Override + public void sessionActivated(ITestingSession newTestingSession) { + if (testingSession != newTestingSession) { + stopUpdateUIJob(); + uiChangesCache.resetChanges(); + + unsubscribeFromSessionEvent(); + testingSession = newTestingSession; + subscribeToSessionEvent(); + + resultsView.updateActionsFromSession(); + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + progressCountPanel.setTestingSession(testingSession); + testsHierarchyViewer.setTestingSession(testingSession); + resultsView.setCaption(testingSession != null ? testingSession.getStatusMessage() : ""); //$NON-NLS-1$ + } + }); + if (newTestingSession != null && !newTestingSession.isFinished()) { + startUpdateUIJob(); + } + } + } + } + + + public UIUpdater(ResultsView resultsView, TestsHierarchyViewer testsHierarchyViewer, ProgressCountPanel progressCountPanel, TestingSessionsManager sessionsManager) { + this.resultsView = resultsView; + this.testsHierarchyViewer = testsHierarchyViewer; + this.progressCountPanel = progressCountPanel; + this.sessionsManager = sessionsManager; + sessionListener = new SessionListener(); + sessionsManagerListener = new TestingSessionsManagerListener(); + sessionsManager.addListener(sessionsManagerListener); + } + + /** + * Returns whether tests hierarchy scrolling should be done during the + * testing process. + * + * @return auto scroll state + */ + public boolean getAutoScroll() { + return autoScroll; + } + + /** + * Sets whether whether tests hierarchy scrolling should be done during the + * testing process. + * + * @param autoScroll new filter state + */ + public void setAutoScroll(boolean autoScroll) { + this.autoScroll = autoScroll; + } + + /** + * Disposes of the UI Updater. Make the necessary clean up. + */ + public void dispose() { + unsubscribeFromSessionEvent(); + sessionsManager.removeListener(sessionsManagerListener); + } + + /** + * Subscribes to the events of currently set testing session. + */ + private void subscribeToSessionEvent() { + if (testingSession != null) { + testingSession.getModelAccessor().addChangesListener(sessionListener); + } + } + + /** + * Unsubscribe from the events of currently set testing session. + */ + private void unsubscribeFromSessionEvent() { + if (testingSession != null) { + testingSession.getModelAccessor().removeChangesListener(sessionListener); + } + } + + /** + * Starts the UI updating job. Stops the previously running (if any). + */ + private void startUpdateUIJob() { + stopUpdateUIJob(); + uiChangesCache.resetChanges(); + updateUIJob = new UpdateUIJob(); + updateUIJob.scheduleSelf(); + } + + /** + * Stops the UI updating job (if any). + */ + private void stopUpdateUIJob() { + if (updateUIJob != null) { + updateUIJob.stop(); + updateUIJob = null; + } + } + + /** + * Fakes the testing session activation and makes all necessary steps to + * handle it. + */ + public void reapplyActiveSession() { + sessionsManagerListener.sessionActivated(sessionsManager.getActiveSession()); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java new file mode 100644 index 00000000000..9db469e8bf8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view; + +import org.eclipse.osgi.util.NLS; + +public class UIViewMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.ui.view.UIViewMessages"; //$NON-NLS-1$ + public static String CounterPanel_tests_erred; + public static String CounterPanel_tests_failed; + public static String CounterPanel_tests_run; + public static String CounterPanel_tests_skipped; + public static String MessagesPanel_label; + public static String MessagesViewer_location_format; + public static String MessagesViewer_message_format; + public static String ResultsView_layout_menu_text; + public static String TestsHierarchyViewer_test_path_format; + public static String TestsHierarchyViewer_test_time_format; + public static String UIUpdater_update_ui_job; + public static String UIUpdater_view_caption_format; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, UIViewMessages.class); + } + + private UIViewMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties new file mode 100644 index 00000000000..f586280fdf5 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties @@ -0,0 +1,22 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +CounterPanel_tests_erred=Errors: +CounterPanel_tests_failed=Failures: +CounterPanel_tests_run=Runs: +CounterPanel_tests_skipped={0} ({1} ignored) +MessagesPanel_label=Messages +MessagesViewer_location_format={0}({1}): +MessagesViewer_message_format={0}{1}: {2} +ResultsView_layout_menu_text=&Layout +TestsHierarchyViewer_test_path_format=\ - {0} +TestsHierarchyViewer_test_time_format=\ ({0} s) +UIUpdater_update_ui_job=Update C/C++ Tests Runner +UIUpdater_view_caption_format={0} - {1} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java new file mode 100644 index 00000000000..1f5097b1c43 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + +import org.eclipse.osgi.util.NLS; + +public class ActionsMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.ui.view.actions.ActionsMessages"; //$NON-NLS-1$ + public static String CopySelectedMessagesAction_text; + public static String CopySelectedMessagesAction_tooltip; + public static String CopySelectedTestsAction_text; + public static String CopySelectedTestsAction_tooltip; + public static String HistoryAction_dialog_button_remove; + public static String HistoryAction_dialog_button_remove_all; + public static String HistoryAction_dialog_limit_label; + public static String HistoryAction_dialog_limit_label_error; + public static String HistoryAction_dialog_list_title; + public static String HistoryAction_dialog_title; + public static String HistoryAction_history_item_clear_text; + public static String HistoryAction_history_item_show_text; + public static String HistoryAction_history_text; + public static String HistoryAction_history_tooltip; + public static String MessageLevelFilterAction_errors_text; + public static String MessageLevelFilterAction_errors_tooltip; + public static String MessageLevelFilterAction_infos_text; + public static String MessageLevelFilterAction_infos_tooltip; + public static String MessageLevelFilterAction_warnings_text; + public static String MessageLevelFilterAction_warnings_tooltip; + public static String MessagesOrderingAction_text; + public static String MessagesOrderingAction_tooltip; + public static String OpenInEditorAction_text; + public static String OpenInEditorAction_tooltip; + public static String RedebugSelectedAction_text; + public static String RedebugSelectedAction_tooltip; + public static String RerunAction_text; + public static String RerunAction_tooltip; + public static String RerunSelectedAction_text; + public static String RerunSelectedAction_tooltip; + public static String ScrollLockAction_name; + public static String ScrollLockAction_tooltip; + public static String ShowFailedOnlyAction_text; + public static String ShowFailedOnlyAction_tooltip; + public static String ShowFileNameOnlyAction_text; + public static String ShowFileNameOnlyAction_tooltip; + public static String ShowNextFailureAction_text; + public static String ShowNextFailureAction_tooltip; + public static String ShowPreviousFailureAction_text; + public static String ShowPreviousFailureAction_tooltip; + public static String ShowTestsInHierarchyAction_text; + public static String ShowTestsInHierarchyAction_tooltip; + public static String ShowTimeAction_text; + public static String ShowTimeAction_tooltip; + public static String StopAction_text; + public static String StopAction_tooltip; + public static String TestsHierarchyCollapseAllAction_text; + public static String TestsHierarchyCollapseAllAction_tooltip; + public static String TestsHierarchyExpandAllAction_text; + public static String TestsHierarchyExpandAllAction_tooltip; + public static String ToggleOrientationAction_automatic_text; + public static String ToggleOrientationAction_horizontal_text; + public static String ToggleOrientationAction_vertical_text; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, ActionsMessages.class); + } + + private ActionsMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties new file mode 100644 index 00000000000..267fc50cfe1 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties @@ -0,0 +1,63 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +CopySelectedMessagesAction_text=&Copy +CopySelectedMessagesAction_tooltip=Copy Selected Messages To Clipboard +CopySelectedTestsAction_text=&Copy +CopySelectedTestsAction_tooltip=Copy Selected Test Names To Clipboard +HistoryAction_dialog_button_remove=&Remove +HistoryAction_dialog_button_remove_all=Remove &All +HistoryAction_dialog_limit_label=&Maximum count of remembered test runs: +HistoryAction_dialog_limit_label_error=Please enter a positive integer smaller than {0}. +HistoryAction_dialog_list_title=Select a test run: +HistoryAction_dialog_title=Test Runs +HistoryAction_history_item_clear_text=&Clear Terminated +HistoryAction_history_item_show_text=History... +HistoryAction_history_text=History +HistoryAction_history_tooltip=Test Run History... +MessageLevelFilterAction_errors_text=&Errors +MessageLevelFilterAction_errors_tooltip=Show error messages +MessageLevelFilterAction_infos_text=&Infos +MessageLevelFilterAction_infos_tooltip=Show information messages +MessageLevelFilterAction_warnings_text=&Warnings +MessageLevelFilterAction_warnings_tooltip=Show warning messages +MessagesOrderingAction_text=Messages &Ordering +MessagesOrderingAction_tooltip=Order Messages By Location, Skip Duplicates +OpenInEditorAction_text=&Go to File +OpenInEditorAction_tooltip=Show File Referred By the Message +RedebugSelectedAction_text=&Debug +RedebugSelectedAction_tooltip=Start Debug Session For Selected Tests +RerunAction_text=Rerun +RerunAction_tooltip=Rerun All Tests +RerunSelectedAction_text=&Run +RerunSelectedAction_tooltip=Rerun Selected Tests +ScrollLockAction_name=Scroll Lock +ScrollLockAction_tooltip=Scroll Lock +ShowFailedOnlyAction_text=Show &Failures Only +ShowFailedOnlyAction_tooltip=Show &Failures Only +ShowFileNameOnlyAction_text=Show File Names Only +ShowFileNameOnlyAction_tooltip=Show Only File Names in Message Locations +ShowNextFailureAction_text=Next Failure +ShowNextFailureAction_tooltip=Next Failed Test +ShowPreviousFailureAction_text=Previous Failure +ShowPreviousFailureAction_tooltip=Previous Failed Test +ShowTestsInHierarchyAction_text=Show Tests in &Hierarchy +ShowTestsInHierarchyAction_tooltip=Show Tests in Hierarchy +ShowTimeAction_text=Show Execution &Time +ShowTimeAction_tooltip=Show Execution Time +StopAction_text=Stop +StopAction_tooltip=Stop Test Run +TestsHierarchyCollapseAllAction_text=C&ollapse All +TestsHierarchyCollapseAllAction_tooltip=Collapse All Nodes +TestsHierarchyExpandAllAction_text=&Expand All +TestsHierarchyExpandAllAction_tooltip=Expand All Nodes +ToggleOrientationAction_automatic_text=&Automatic +ToggleOrientationAction_horizontal_text=&Horizontal +ToggleOrientationAction_vertical_text=&Vertical diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java new file mode 100644 index 00000000000..bcad308feef --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import java.util.Iterator; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.IWorkbenchCommandConstants; + +/** + * Copies the selected test messages to the clipboard. + */ +public class CopySelectedMessagesAction extends Action { + + private Clipboard clipboard; + private TableViewer tableViewer; + + + public CopySelectedMessagesAction(TableViewer tableViewer, Clipboard clipboard) { + super(ActionsMessages.CopySelectedMessagesAction_text); + setToolTipText(ActionsMessages.CopySelectedMessagesAction_tooltip); + setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY); + this.tableViewer = tableViewer; + this.clipboard = clipboard; + } + + @Override + public void run() { + ITableLabelProvider labelProvider = (ITableLabelProvider)tableViewer.getLabelProvider(); + IStructuredSelection selection = (IStructuredSelection)tableViewer.getSelection(); + if (!selection.isEmpty()) { + StringBuilder sb = new StringBuilder(); + boolean needEOL = false; + for (Iterator it = selection.iterator(); it.hasNext();) { + Object item = it.next(); + if (needEOL) { + sb.append(System.getProperty("line.separator")); //$NON-NLS-1$ + } else { + needEOL = true; + } + sb.append(labelProvider.getColumnText(item, 0)); + } + clipboard.setContents( + new String[]{ sb.toString() }, + new Transfer[]{ TextTransfer.getInstance() }); + } + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java new file mode 100644 index 00000000000..488abcdbaf4 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import java.util.Iterator; + +import org.eclipse.cdt.testsrunner.internal.ui.view.TestPathUtils; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.IWorkbenchCommandConstants; + +/** + * Copies the name of the selected test items (test suites or cases) to the + * clipboard. + */ +public class CopySelectedTestsAction extends Action { + + private TreeViewer treeViewer; + private Clipboard clipboard; + + + public CopySelectedTestsAction(TreeViewer treeViewer, Clipboard clipboard) { + super(ActionsMessages.CopySelectedTestsAction_text); + setToolTipText(ActionsMessages.CopySelectedTestsAction_tooltip); + setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY); + this.treeViewer = treeViewer; + this.clipboard = clipboard; + } + + @Override + public void run() { + IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection(); + if (!selection.isEmpty()) { + StringBuilder sb = new StringBuilder(); + boolean needEOL = false; + for (Iterator it = selection.iterator(); it.hasNext();) { + if (needEOL) { + sb.append(System.getProperty("line.separator")); //$NON-NLS-1$ + } else { + needEOL = true; + } + sb.append(TestPathUtils.getTestItemPath((ITestItem)it.next())); + } + clipboard.setContents( + new String[]{ sb.toString() }, + new Transfer[]{ TextTransfer.getInstance() }); + } + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java new file mode 100644 index 00000000000..788879ef15d --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java @@ -0,0 +1,448 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IListAdapter; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuCreator; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; + +/** + * Shows the testing sessions history in drop down list. + */ +public class HistoryDropDownAction extends Action { + + /** + * The dialog for testing sessions history management. Allows to browse, + * activate and remove the selected testing sessions and to set testing + * sessions history size limit. + */ + private class HistoryListDialog extends StatusDialog { + + /** Max value for the history size limit that may be set via the dialog. */ + private static final int MAX_HISTORY_SIZE_LIMIT = 100; + + /** Testing sessions history list. */ + private ListDialogField historyList; + + /** String field that allows to set testing sessions history size limit. */ + private StringDialogField historySizeLimitField; + + /** Currently set testing sessions history size limit. */ + private int historySizeLimit; + + /** The currently selected active testing session. */ + private ITestingSession resultActiveSession; + + + /** + * Label provider for the dialog testing sessions list. + */ + private final class TestRunLabelProvider extends LabelProvider { + + @Override + public String getText(Object element) { + return ((ITestingSession)element).getName(); + } + + } + + + private HistoryListDialog(Shell shell) { + super(shell); + setHelpAvailable(false); + setTitle(ActionsMessages.HistoryAction_dialog_title); + + createHistoryList(); + createHistorySizeLimitField(); + } + + @Override + protected boolean isResizable() { + return true; + } + + /** + * Fills the testing sessions history list. + */ + private void createHistoryList() { + IListAdapter adapter = new IListAdapter() { + @Override + public void customButtonPressed(ListDialogField field, int index) { + doCustomButtonPressed(index); + } + @Override + public void selectionChanged(ListDialogField field) { + doSelectionChanged(); + } + + @Override + public void doubleClicked(ListDialogField field) { + doDoubleClicked(); + } + }; + String[] buttonLabels = new String[] { ActionsMessages.HistoryAction_dialog_button_remove, ActionsMessages.HistoryAction_dialog_button_remove_all }; + LabelProvider labelProvider = new TestRunLabelProvider(); + historyList = new ListDialogField(adapter, buttonLabels, labelProvider); + historyList.setLabelText(ActionsMessages.HistoryAction_dialog_list_title); + + historyList.setElements(testingSessionsManager.getSessions()); + Object currentEntry = testingSessionsManager.getActiveSession(); + ISelection sel = (currentEntry != null) ? new StructuredSelection(currentEntry) : new StructuredSelection(); + historyList.selectElements(sel); + } + + /** + * Initializes history size limit field of the dialog. + */ + private void createHistorySizeLimitField() { + historySizeLimitField = new StringDialogField(); + historySizeLimitField.setLabelText(ActionsMessages.HistoryAction_dialog_limit_label); + historySizeLimitField.setDialogFieldListener(new IDialogFieldListener() { + @Override + public void dialogFieldChanged(DialogField field) { + String maxString = historySizeLimitField.getText(); + boolean valid; + try { + historySizeLimit = Integer.parseInt(maxString); + valid = historySizeLimit > 0 && historySizeLimit < MAX_HISTORY_SIZE_LIMIT; + } catch (NumberFormatException e) { + valid = false; + } + IStatus status = valid ? StatusInfo.OK_STATUS : new StatusInfo(IStatus.ERROR, + MessageFormat.format(ActionsMessages.HistoryAction_dialog_limit_label_error, + Integer.toString(MAX_HISTORY_SIZE_LIMIT) + ) + ); + updateStatus(status); + } + }); + historySizeLimitField.setText(Integer.toString(testingSessionsManager.getHistorySizeLimit())); + } + + @Override + protected Control createDialogArea(Composite parent) { + initializeDialogUnits(parent); + + Composite composite = (Composite) super.createDialogArea(parent); + + Composite inner = new Composite(composite, SWT.NONE); + inner.setLayoutData(new GridData(GridData.FILL_BOTH)); + inner.setFont(composite.getFont()); + + LayoutUtil.doDefaultLayout(inner, new DialogField[] { historyList, new org.eclipse.cdt.internal.ui.wizards.dialogfields.Separator() }, true); + LayoutUtil.setHeightHint(historyList.getListControl(null), convertHeightInCharsToPixels(12)); + LayoutUtil.setHorizontalGrabbing(historyList.getListControl(null)); + + Composite additionalControls = new Composite(inner, SWT.NONE); + additionalControls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + LayoutUtil.doDefaultLayout(additionalControls, new DialogField[] { historySizeLimitField }, false); + LayoutUtil.setHorizontalGrabbing(historySizeLimitField.getTextControl(null)); + + applyDialogFont(composite); + return composite; + } + + /** + * Processes dialog custom button pressing. + * + * @param index index of the button + */ + private void doCustomButtonPressed(int index) { + switch (index) { + case 0: // remove + historyList.removeElements(historyList.getSelectedElements()); + historyList.selectFirstElement(); + break; + + case 1: // remove all + historyList.removeAllElements(); + break; + default: + break; + } + } + + /** + * Processes double click on the item in dialog. + */ + private void doDoubleClicked() { + okPressed(); + } + + /** + * Processes the selection change in the dialog + */ + private void doSelectionChanged() { + List selected = historyList.getSelectedElements(); + if (selected.size() >= 1) { + resultActiveSession = selected.get(0); + } else { + resultActiveSession = null; + } + historyList.enableButton(0, selected.size() != 0); + } + + /** + * Provides access to the active session currently selected by user. + * + * @return testing session + */ + public ITestingSession getResultActiveSession() { + return resultActiveSession; + } + + /** + * Provides access to the testing sessions history list edited by user. + * + * @return list of testing sessions + */ + public List getResultSessions() { + return historyList.getElements(); + } + + /** + * Provides access to value of history size limit specified by user. + * + * @return history size limit + */ + public int getResultHistorySizeLimit() { + return historySizeLimit; + } + } + + + /** + * Represents a testing sessions history item. + */ + private class HistoryAction extends Action { + + /** Testing session of the history item. */ + private final ITestingSession testingSession; + + public HistoryAction(int testingSessionIndex, ITestingSession testingSession) { + super("", AS_RADIO_BUTTON); //$NON-NLS-1$ + this.testingSession = testingSession; + + // Generate action text + String label = testingSession.getName(); + if (testingSessionIndex < 10) { + // Add the numerical accelerator + label = new StringBuilder().append('&').append(testingSessionIndex).append(' ').append(label).toString(); + } + setText(label); + } + + @Override + public void run() { + if (isChecked()) { + testingSessionsManager.setActiveSession(testingSession); + } + } + } + + + /** + * Provides access to the history list management dialog. + */ + private class HistoryListAction extends Action { + + public HistoryListAction() { + super(ActionsMessages.HistoryAction_history_item_show_text, AS_RADIO_BUTTON); + } + + @Override + public void run() { + if (isChecked()) { + runHistoryDialog(); + } + } + } + + + /** + * Removes the terminated testing sessions from the history list. + */ + private class ClearAction extends Action { + + public ClearAction() { + setText(ActionsMessages.HistoryAction_history_item_clear_text); + + boolean enabled = false; + for (ITestingSession testingSession : testingSessionsManager.getSessions()) { + if (testingSession.isFinished()) { + enabled = true; + break; + } + } + setEnabled(enabled); + } + + @Override + public void run() { + List remainingSessions = new ArrayList(); + for (ITestingSession testingSession : testingSessionsManager.getSessions()) { + if (!testingSession.isFinished()) { + remainingSessions.add(testingSession); + } + } + + ITestingSession newActiveSession = remainingSessions.isEmpty() ? null : remainingSessions.get(0); + testingSessionsManager.setActiveSession(newActiveSession); + testingSessionsManager.setSessions(remainingSessions); + } + } + + + /** + * Represents the testing sessions history menu factory. + */ + private class HistoryMenuCreator implements IMenuCreator { + + @Override + public Menu getMenu(Menu parent) { + return null; + } + + @Override + public Menu getMenu(Control parent) { + if (menu != null) { + menu.dispose(); + } + final MenuManager manager = new MenuManager(); + manager.setRemoveAllWhenShown(true); + manager.addMenuListener(new IMenuListener() { + @Override + public void menuAboutToShow(IMenuManager manager2) { + boolean checkOthers = addHistoryItems(manager2); + + Action others = new HistoryListAction(); + others.setChecked(checkOthers); + manager2.add(others); + manager2.add(new Separator()); + manager2.add(new ClearAction()); + } + + private boolean addHistoryItems(IMenuManager manager) { + boolean checkOthers = true; + + int sessionsCount = testingSessionsManager.getSessionsCount(); + if (sessionsCount == 0) { + return false; + } + int menuItemsCount = Math.min(sessionsCount, RESULTS_IN_DROP_DOWN_MENU); + + ITestingSession activeSession = testingSessionsManager.getActiveSession(); + int testingSessionIndex = 0; + for (ITestingSession testingSession : testingSessionsManager.getSessions()) { + if (testingSessionIndex >= menuItemsCount) { + break; + } + HistoryAction action = new HistoryAction(testingSessionIndex, testingSession); + boolean check = (testingSession == activeSession); + action.setChecked(check); + if (check) { + checkOthers = false; + } + manager.add(action); + testingSessionIndex++; + } + + return checkOthers; + } + }); + + menu = manager.createContextMenu(parent); + return menu; + } + + @Override + public void dispose() { + if (menu != null) { + menu.dispose(); + menu = null; + } + } + } + + + /** Defines how many history items should be showed in drop down history menu. */ + public static final int RESULTS_IN_DROP_DOWN_MENU = 10; + + /** Accessor to the Testing Sessions Plug-in Manager. */ + private TestingSessionsManager testingSessionsManager; + + /** Required for the history dialog. */ + private Shell shell; + + /** Drop down menu */ + private Menu menu; + + + public HistoryDropDownAction(TestingSessionsManager testingSessionsManager, Shell shell) { + super(ActionsMessages.HistoryAction_history_text); + setToolTipText(ActionsMessages.HistoryAction_history_tooltip); + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/history_list.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/history_list.gif")); //$NON-NLS-1$ + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/history_list.gif")); //$NON-NLS-1$ + this.testingSessionsManager = testingSessionsManager; + this.shell = shell; + setMenuCreator(new HistoryMenuCreator()); + } + + /** + * Shows the testing sessions history dialog. + */ + private void runHistoryDialog() { + HistoryListDialog dialog = new HistoryListDialog(shell); + if (dialog.open() == Window.OK) { + testingSessionsManager.setHistorySizeLimit(dialog.getResultHistorySizeLimit()); + testingSessionsManager.setActiveSession(dialog.getResultActiveSession()); + testingSessionsManager.setSessions(dialog.getResultSessions()); + } + } + + @Override + public void run() { + runHistoryDialog(); + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessageLevelFilterAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessageLevelFilterAction.java new file mode 100644 index 00000000000..5eba4424260 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessageLevelFilterAction.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.ui.view.MessagesViewer; +import org.eclipse.jface.action.Action; +import org.eclipse.ui.PlatformUI; + +/** + * Represents a filtering action for test messages. It is used for all kind of + * filters (info, warnings, errors). + */ +public class MessageLevelFilterAction extends Action { + + private MessagesViewer.LevelFilter levelFilter; + private MessagesViewer messagesViewer; + + + public MessageLevelFilterAction(MessagesViewer messagePanel, MessagesViewer.LevelFilter levelFilter, boolean checked) { + super("", AS_CHECK_BOX); //$NON-NLS-1$ + this.levelFilter = levelFilter; + this.messagesViewer = messagePanel; + if (levelFilter == MessagesViewer.LevelFilter.Info) { + setText(ActionsMessages.MessageLevelFilterAction_infos_text); + setToolTipText(ActionsMessages.MessageLevelFilterAction_infos_tooltip); + } else if (levelFilter == MessagesViewer.LevelFilter.Warning) { + setText(ActionsMessages.MessageLevelFilterAction_warnings_text); + setToolTipText(ActionsMessages.MessageLevelFilterAction_warnings_tooltip); + } else if (levelFilter == MessagesViewer.LevelFilter.Error) { + setText(ActionsMessages.MessageLevelFilterAction_errors_text); + setToolTipText(ActionsMessages.MessageLevelFilterAction_errors_tooltip); + } + setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(levelFilter.getImageId())); + setChecked(checked); + if (checked) { + messagePanel.addLevelFilter(levelFilter, false); + } + } + + @Override + public void run() { + if (isChecked()) { + messagesViewer.addLevelFilter(levelFilter, true); + } else { + messagesViewer.removeLevelFilter(levelFilter); + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessagesOrderingAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessagesOrderingAction.java new file mode 100644 index 00000000000..b7e032a07bd --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessagesOrderingAction.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.MessagesViewer; +import org.eclipse.jface.action.Action; + +/** + * Turns on/off the messages ordering by location. + */ +public class MessagesOrderingAction extends Action { + + private MessagesViewer messagesViewer; + + + public MessagesOrderingAction(MessagesViewer messagesViewer) { + super("", AS_CHECK_BOX); //$NON-NLS-1$ + this.messagesViewer = messagesViewer; + setText(ActionsMessages.MessagesOrderingAction_text); + setToolTipText(ActionsMessages.MessagesOrderingAction_tooltip); + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/sort.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/sort.gif")); //$NON-NLS-1$ + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/sort.gif")); //$NON-NLS-1$ + setChecked(messagesViewer.getOrderingMode()); + } + + @Override + public void run() { + messagesViewer.setOrderingMode(isChecked()); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/OpenInEditorAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/OpenInEditorAction.java new file mode 100644 index 00000000000..5438d5b38d6 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/OpenInEditorAction.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import java.net.URI; + +import org.eclipse.cdt.debug.ui.CDebugUIPlugin; +import org.eclipse.cdt.debug.core.CDebugCorePlugin; +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.model.ITestLocation; +import org.eclipse.cdt.testsrunner.model.ITestMessage; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.IPersistableSourceLocator; +import org.eclipse.debug.core.model.ISourceLocator; +import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector; +import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant; +import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugModelPresentation; +import org.eclipse.debug.ui.sourcelookup.ISourceLookupResult; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Opens the editor in place where the currently selected message is pointed to. + */ +public class OpenInEditorAction extends Action { + + private TableViewer messagesViewer; + private TestingSessionsManager testingSessionsManager; + private IWorkbench workbench; + + + public OpenInEditorAction(TableViewer tableViewer, TestingSessionsManager testingSessionsManager, IWorkbench workbench) { + super(ActionsMessages.OpenInEditorAction_text); + this.messagesViewer = tableViewer; + this.testingSessionsManager = testingSessionsManager; + this.workbench = workbench; + setToolTipText(ActionsMessages.OpenInEditorAction_tooltip); + } + + @Override + public void run() { + Object selectedObject = ((IStructuredSelection)messagesViewer.getSelection()).getFirstElement(); + if (selectedObject != null && selectedObject instanceof ITestMessage) { + ITestLocation messageLocation = ((ITestMessage)selectedObject).getLocation(); + if (messageLocation != null) { + ILaunch launch = testingSessionsManager.getActiveSession().getLaunch(); + lookupSource(messageLocation, launch); + } + } + } + + // NOTE: This method is copied from Linux Tools Project (http://www.eclipse.org/linuxtools). + // Valgrind Support Plugin is implementing similar functionality so it is just reused. + // See also org.eclipse.linuxtools.valgrind.ui/src/org/eclipse/linuxtools/internal/valgrind/ui/CoreMessagesViewer.java + private void lookupSource(ITestLocation messageLocation, ILaunch launch) { + ISourceLocator locator = launch.getSourceLocator(); + if (locator instanceof AbstractSourceLookupDirector) { + AbstractSourceLookupDirector director = (AbstractSourceLookupDirector) locator; + ISourceLookupParticipant[] participants = director.getParticipants(); + if (participants.length == 0) { + // source locator likely disposed, try recreating it + IPersistableSourceLocator sourceLocator; + ILaunchConfiguration config = launch.getLaunchConfiguration(); + if (config != null) { + try { + String id = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String) null); + if (id == null) { + sourceLocator = CDebugUIPlugin.createDefaultSourceLocator(); + sourceLocator.initializeDefaults(config); + } else { + sourceLocator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(id); + String memento = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null); + if (memento == null) { + sourceLocator.initializeDefaults(config); + } else { + sourceLocator.initializeFromMemento(memento); + } + } + + // replace old source locator + locator = sourceLocator; + launch.setSourceLocator(sourceLocator); + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + } + ISourceLookupResult result = DebugUITools.lookupSource(messageLocation.getFile(), locator); + try { + openEditorAndSelect(result, messageLocation.getLine()); + } catch (PartInitException e) { + TestsRunnerPlugin.log(e); + } catch (BadLocationException e) { + TestsRunnerPlugin.log(e); + } + } + + // NOTE: This method is copied from Linux Tools Project (http://www.eclipse.org/linuxtools). + // Valgrind Support Plugin is implementing similar functionality so it is just reused. + // See also org.eclipse.linuxtools.valgrind.ui/src/org/eclipse/linuxtools/internal/valgrind/ui/CoreMessagesViewer.java + private void openEditorAndSelect(ISourceLookupResult result, int line) throws PartInitException, BadLocationException { + IEditorInput input = result.getEditorInput(); + String editorID = result.getEditorId(); + + if (input == null || editorID == null) { + // Consult the CDT DebugModelPresentation + Object sourceElement = result.getSourceElement(); + if (sourceElement != null) { + // Resolve IResource in case we get a LocalFileStorage object + if (sourceElement instanceof LocalFileStorage) { + IPath filePath = ((LocalFileStorage) sourceElement).getFullPath(); + URI fileURI = URIUtil.toURI(filePath); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IFile[] files = root.findFilesForLocationURI(fileURI); + if (files.length > 0) { + // Take the first match + sourceElement = files[0]; + } + } + + IDebugModelPresentation pres = DebugUITools.newDebugModelPresentation(CDebugCorePlugin.getUniqueIdentifier()); + input = pres.getEditorInput(sourceElement); + editorID = pres.getEditorId(input, sourceElement); + pres.dispose(); + } + } + if (input != null && editorID != null) { + // Open the editor + IWorkbenchPage activePage = workbench.getActiveWorkbenchWindow().getActivePage(); + + IEditorPart editor = IDE.openEditor(activePage, input, editorID); + // Select the line + if (editor instanceof ITextEditor) { + ITextEditor textEditor = (ITextEditor) editor; + + if (line > 0) { + IDocumentProvider provider = textEditor.getDocumentProvider(); + IDocument document = provider.getDocument(textEditor.getEditorInput()); + + IRegion lineRegion = document.getLineInformation(line - 1); //zero-indexed + textEditor.selectAndReveal(lineRegion.getOffset(), lineRegion.getLength()); + } + } + } + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RedebugSelectedAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RedebugSelectedAction.java new file mode 100644 index 00000000000..a6b670dbbb7 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RedebugSelectedAction.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.jface.viewers.TreeViewer; + +/** + * Launches the new debug session for the currently selected items of test + * hierarchy. + */ +public class RedebugSelectedAction extends RelaunchSelectedAction { + + public RedebugSelectedAction(ITestingSession testingSession, TreeViewer treeViewer) { + super(testingSession, treeViewer); + setText(ActionsMessages.RedebugSelectedAction_text); + setToolTipText(ActionsMessages.RedebugSelectedAction_tooltip); + } + + @Override + protected String getLaunchMode() { + return ILaunchManager.DEBUG_MODE; + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RelaunchSelectedAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RelaunchSelectedAction.java new file mode 100644 index 00000000000..b40e0d6ab86 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RelaunchSelectedAction.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.launcher.ITestsLaunchConfigurationConstants; +import org.eclipse.cdt.testsrunner.internal.ui.view.TestPathUtils; +import org.eclipse.cdt.testsrunner.model.ITestItem; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; + +/** + * Launches the new run or debug session for the currently selected items of + * test hierarchy. + */ +public abstract class RelaunchSelectedAction extends Action { + + private ITestingSession testingSession; + private TreeViewer treeViewer; + + + public RelaunchSelectedAction(ITestingSession testingSession, TreeViewer treeViewer) { + this.testingSession = testingSession; + this.treeViewer = treeViewer; + } + + /** + * Returns the launch mode that should be use to run selected test item. + * + * @return launch mode + */ + protected abstract String getLaunchMode(); + + @Override + public void run() { + if (testingSession != null) { + try { + ILaunch launch = testingSession.getLaunch(); + ILaunchConfigurationWorkingCopy launchConf = launch.getLaunchConfiguration().getWorkingCopy(); + List testsFilterAttr = Arrays.asList(TestPathUtils.packTestPaths(getSelectedTestItems())); + launchConf.setAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_FILTER, testsFilterAttr); + DebugUITools.launch(launchConf, getLaunchMode()); + return; + } catch (CoreException e) { + TestsRunnerPlugin.log(e); + } + } + setEnabled(false); + } + + /** + * Returns the currently selected items of test hierarchy. + * + * @return array of test items + */ + private ITestItem[] getSelectedTestItems() { + IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection(); + ITestItem[] result = new ITestItem[selection.size()]; + int resultIndex = 0; + for (Iterator it = selection.iterator(); it.hasNext();) { + result[resultIndex] = (ITestItem)it.next(); + ++resultIndex; + } + return result; + } + + /** + * Sets actual testing session. + * + * @param testingSession testing session + */ + public void setTestingSession(ITestingSession testingSession) { + this.testingSession = testingSession; + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunAction.java new file mode 100644 index 00000000000..54da1a7163f --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunAction.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.jface.action.Action; + +/** + * Restarts the last testing session (it may be run or debug session). + */ +public class RerunAction extends Action { + + private TestingSessionsManager testingSessionsManager; + + + public RerunAction(TestingSessionsManager testingSessionsManager) { + super(ActionsMessages.RerunAction_text); + setToolTipText(ActionsMessages.RerunAction_tooltip); + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/rerun.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/rerun.gif")); //$NON-NLS-1$ + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/rerun.gif")); //$NON-NLS-1$ + this.testingSessionsManager = testingSessionsManager; + } + + @Override + public void run() { + ITestingSession activeSession = testingSessionsManager.getActiveSession(); + if (activeSession != null) { + ILaunch launch = activeSession.getLaunch(); + DebugUITools.launch(launch.getLaunchConfiguration(), launch.getLaunchMode()); + } else { + setEnabled(false); + } + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunSelectedAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunSelectedAction.java new file mode 100644 index 00000000000..29d57942e41 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunSelectedAction.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.jface.viewers.TreeViewer; + +/** + * Launches the new run session for the currently selected items of test + * hierarchy. + */ +public class RerunSelectedAction extends RelaunchSelectedAction { + + public RerunSelectedAction(ITestingSession testingSession, TreeViewer treeViewer) { + super(testingSession, treeViewer); + setText(ActionsMessages.RerunSelectedAction_text); + setToolTipText(ActionsMessages.RerunSelectedAction_tooltip); + } + + @Override + protected String getLaunchMode() { + return ILaunchManager.RUN_MODE; + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ScrollLockAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ScrollLockAction.java new file mode 100644 index 00000000000..841b8ec408d --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ScrollLockAction.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.UIUpdater; +import org.eclipse.jface.action.Action; + +/** + * Toggles the auto-scroll for tests hierarchy tree. + */ +public class ScrollLockAction extends Action { + + private UIUpdater modelSyncronizer; + + + public ScrollLockAction(UIUpdater modelSyncronizer) { + super(ActionsMessages.ScrollLockAction_name); + this.modelSyncronizer = modelSyncronizer; + setToolTipText(ActionsMessages.ScrollLockAction_tooltip); + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/scroll_lock.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/scroll_lock.gif")); //$NON-NLS-1$ + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/scroll_lock.gif")); //$NON-NLS-1$ + setChecked(!this.modelSyncronizer.getAutoScroll()); + } + + @Override + public void run() { + modelSyncronizer.setAutoScroll(!isChecked()); + } +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFailedOnlyAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFailedOnlyAction.java new file mode 100644 index 00000000000..13d2ee5f5cd --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFailedOnlyAction.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.ResultsPanel; +import org.eclipse.jface.action.Action; + +/** + * Toggles the filter for the passed test items. + */ +public class ShowFailedOnlyAction extends Action { + + private ResultsPanel resultsPanel; + + + public ShowFailedOnlyAction(ResultsPanel resultsPanel) { + super("", AS_CHECK_BOX); //$NON-NLS-1$ + this.resultsPanel = resultsPanel; + setText(ActionsMessages.ShowFailedOnlyAction_text); + setToolTipText(ActionsMessages.ShowFailedOnlyAction_tooltip); + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("obj16/show_failed_only.gif")); //$NON-NLS-1$ + setChecked(resultsPanel.getShowFailedOnly()); + } + + @Override + public void run() { + resultsPanel.setShowFailedOnly(isChecked()); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFileNameOnlyAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFileNameOnlyAction.java new file mode 100644 index 00000000000..a9fdf4914d0 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFileNameOnlyAction.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.ui.view.MessagesViewer; +import org.eclipse.jface.action.Action; + +/** + * Toggles the short or long view for file paths in message locations. The short + * view shows only the file names instead of full paths. + */ +public class ShowFileNameOnlyAction extends Action { + + private MessagesViewer messagesViewer; + + + public ShowFileNameOnlyAction(MessagesViewer messagesViewer) { + super(ActionsMessages.ShowFileNameOnlyAction_text, AS_CHECK_BOX); + this.messagesViewer = messagesViewer; + setToolTipText(ActionsMessages.ShowFileNameOnlyAction_tooltip); + setChecked(messagesViewer.getShowFileNameOnly()); + } + + @Override + public void run() { + messagesViewer.setShowFileNameOnly(isChecked()); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowNextFailureAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowNextFailureAction.java new file mode 100644 index 00000000000..e337b03fcad --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowNextFailureAction.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.TestsHierarchyViewer; +import org.eclipse.jface.action.Action; + +/** + * Looks for the next failed test case in tests hierarchy (corresponding to the + * currently selected one). + */ +public class ShowNextFailureAction extends Action { + + private TestsHierarchyViewer testsHierarchyViewer; + + public ShowNextFailureAction(TestsHierarchyViewer testsHierarchyViewer) { + super(ActionsMessages.ShowNextFailureAction_text); + this.testsHierarchyViewer = testsHierarchyViewer; + setToolTipText(ActionsMessages.ShowNextFailureAction_tooltip); + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/show_next.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/show_next.gif")); //$NON-NLS-1$ + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/show_next.gif")); //$NON-NLS-1$ + } + + @Override + public void run() { + testsHierarchyViewer.showNextFailure(); + } +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowPreviousFailureAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowPreviousFailureAction.java new file mode 100644 index 00000000000..79c43502e7f --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowPreviousFailureAction.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.TestsHierarchyViewer; +import org.eclipse.jface.action.Action; + +/** + * Looks for the previous failed test case in tests hierarchy (corresponding to the + * currently selected one). + */ +public class ShowPreviousFailureAction extends Action { + + private TestsHierarchyViewer testsHierarchyViewer; + + public ShowPreviousFailureAction(TestsHierarchyViewer testsHierarchyViewer) { + super(ActionsMessages.ShowPreviousFailureAction_text); + this.testsHierarchyViewer = testsHierarchyViewer; + setToolTipText(ActionsMessages.ShowPreviousFailureAction_tooltip); + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/show_previous.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/show_previous.gif")); //$NON-NLS-1$ + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/show_previous.gif")); //$NON-NLS-1$ + } + + @Override + public void run() { + testsHierarchyViewer.showPreviousFailure(); + } +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTestsInHierarchyAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTestsInHierarchyAction.java new file mode 100644 index 00000000000..ab4869cedf8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTestsInHierarchyAction.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.TestsHierarchyViewer; +import org.eclipse.jface.action.Action; + +/** + * Specifies whether tests hierarchy should be shown in hierarchical or flat + * view. + */ +public class ShowTestsInHierarchyAction extends Action { + + private TestsHierarchyViewer testsHierarchyViewer; + + + public ShowTestsInHierarchyAction(TestsHierarchyViewer testsHierarchyViewer) { + super(ActionsMessages.ShowTestsInHierarchyAction_text, AS_CHECK_BOX); + this.testsHierarchyViewer = testsHierarchyViewer; + setToolTipText(ActionsMessages.ShowTestsInHierarchyAction_tooltip); + setChecked(testsHierarchyViewer.showTestsHierarchy()); + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/show_tests_hierarchy.gif")); //$NON-NLS-1$ + } + + @Override + public void run() { + testsHierarchyViewer.setShowTestsHierarchy(isChecked()); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTimeAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTimeAction.java new file mode 100644 index 00000000000..c312bdcebb8 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTimeAction.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.ui.view.TestsHierarchyViewer; +import org.eclipse.jface.action.Action; + +/** + * Toggles the test execution time showing in tests hierarchy viewer. + */ +public class ShowTimeAction extends Action { + + private TestsHierarchyViewer testsHierarchyViewer; + + + public ShowTimeAction(TestsHierarchyViewer testsHierarchyViewer) { + super(ActionsMessages.ShowTimeAction_text, AS_CHECK_BOX); + this.testsHierarchyViewer = testsHierarchyViewer; + setToolTipText(ActionsMessages.ShowTimeAction_tooltip); + setChecked(testsHierarchyViewer.showTime()); + } + + @Override + public void run() { + testsHierarchyViewer.setShowTime(isChecked()); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/StopAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/StopAction.java new file mode 100644 index 00000000000..e6905998d68 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/StopAction.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager; +import org.eclipse.cdt.testsrunner.model.ITestingSession; +import org.eclipse.jface.action.Action; + +/** + * Stops running of the active testing session. + */ +public class StopAction extends Action { + + private TestingSessionsManager testingSessionsManager; + + + public StopAction(TestingSessionsManager testingSessionsManager) { + super(ActionsMessages.StopAction_text); + setToolTipText(ActionsMessages.StopAction_tooltip); + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/stop.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/stop.gif")); //$NON-NLS-1$ + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/stop.gif")); //$NON-NLS-1$ + this.testingSessionsManager = testingSessionsManager; + } + + @Override + public void run() { + ITestingSession activeSession = testingSessionsManager.getActiveSession(); + if (activeSession != null) { + activeSession.stop(); + } + setEnabled(false); + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyCollapseAllAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyCollapseAllAction.java new file mode 100644 index 00000000000..c42a42cb1ea --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyCollapseAllAction.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.AbstractTreeViewer; + +/** + * Collapses the tests hierarchy tree in the viewer. + */ +public class TestsHierarchyCollapseAllAction extends Action { + + private AbstractTreeViewer testsHierarchyTreeViewer; + + + public TestsHierarchyCollapseAllAction(AbstractTreeViewer testsHierarchyTreeViewer) { + setText(ActionsMessages.TestsHierarchyCollapseAllAction_text); + setToolTipText(ActionsMessages.TestsHierarchyCollapseAllAction_tooltip); + this.testsHierarchyTreeViewer = testsHierarchyTreeViewer; + } + + @Override + public void run(){ + testsHierarchyTreeViewer.collapseAll(); + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyExpandAllAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyExpandAllAction.java new file mode 100644 index 00000000000..a48ba783adb --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyExpandAllAction.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.AbstractTreeViewer; + +/** + * Expands the tests hierarchy tree in the viewer. + */ +public class TestsHierarchyExpandAllAction extends Action { + + private AbstractTreeViewer testsHierarchyTreeViewer; + + + public TestsHierarchyExpandAllAction(AbstractTreeViewer testsHierarchyTreeViewer) { + setText(ActionsMessages.TestsHierarchyExpandAllAction_text); + setToolTipText(ActionsMessages.TestsHierarchyExpandAllAction_tooltip); + this.testsHierarchyTreeViewer = testsHierarchyTreeViewer; + } + + @Override + public void run(){ + testsHierarchyTreeViewer.expandAll(); + } + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ToggleOrientationAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ToggleOrientationAction.java new file mode 100644 index 00000000000..1ecaafe8ed5 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ToggleOrientationAction.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.ui.view.actions; + + +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.ui.view.ResultsView; +import org.eclipse.jface.action.Action; + +/** + * Toggles the orientation of the view. + */ +public class ToggleOrientationAction extends Action { + + private ResultsView resultsView; + private ResultsView.Orientation orientation; + + + public ToggleOrientationAction(ResultsView resultsView, ResultsView.Orientation orientation) { + super("", AS_RADIO_BUTTON); //$NON-NLS-1$ + this.resultsView = resultsView; + if (orientation == ResultsView.Orientation.Horizontal) { + setText(ActionsMessages.ToggleOrientationAction_horizontal_text); + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/orientation_horizontal.gif")); //$NON-NLS-1$ + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/orientation_horizontal.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/orientation_horizontal.gif")); //$NON-NLS-1$ + } else if (orientation == ResultsView.Orientation.Vertical) { + setText(ActionsMessages.ToggleOrientationAction_vertical_text); + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/orientation_vertical.gif")); //$NON-NLS-1$ + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/orientation_vertical.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/orientation_vertical.gif")); //$NON-NLS-1$ + } else if (orientation == ResultsView.Orientation.Auto) { + setText(ActionsMessages.ToggleOrientationAction_automatic_text); + setImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/orientation_auto.gif")); //$NON-NLS-1$ + setDisabledImageDescriptor(TestsRunnerPlugin.getImageDescriptor("dlcl16/orientation_auto.gif")); //$NON-NLS-1$ + setHoverImageDescriptor(TestsRunnerPlugin.getImageDescriptor("elcl16/orientation_auto.gif")); //$NON-NLS-1$ + } + this.orientation = orientation; + } + + public ResultsView.Orientation getOrientation() { + return orientation; + } + + @Override + public void run() { + if (isChecked()) { + resultsView.setOrientation(orientation); + } + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/BaseTestsLaunchDelegate.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/BaseTestsLaunchDelegate.java new file mode 100644 index 00000000000..2effdce8899 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/BaseTestsLaunchDelegate.java @@ -0,0 +1,255 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.launcher; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin; +import org.eclipse.cdt.testsrunner.internal.launcher.ITestsLaunchConfigurationConstants; +import org.eclipse.cdt.testsrunner.internal.launcher.LauncherMessages; +import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo; +import org.eclipse.cdt.testsrunner.internal.ui.view.TestPathUtils; +import org.eclipse.cdt.testsrunner.model.TestingException; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchDelegate; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2; +import org.eclipse.debug.core.model.LaunchConfigurationDelegate; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; + +/** + * Launch delegate implementation that redirects its queries to the preferred + * launch delegate, correcting the arguments attribute (to take into account + * auto generated test module parameters) and setting up the custom process + * factory (to handle testing process IO streams). + */ +public abstract class BaseTestsLaunchDelegate extends LaunchConfigurationDelegate { + + /** Stores the changes made to the launch configuration. */ + private Map changesToLaunchConfiguration = new HashMap(); + + + @Override + public ILaunch getLaunch(ILaunchConfiguration config, String mode) throws CoreException { + return getPreferredDelegate(config, mode).getLaunch(config, mode); + } + + @Override + public boolean buildForLaunch(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException { + return getPreferredDelegate(config, mode).buildForLaunch(config, mode, monitor); + } + + @Override + public boolean finalLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException { + return getPreferredDelegate(config, mode).finalLaunchCheck(config, mode, monitor); + } + + @Override + public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException { + return getPreferredDelegate(config, mode).preLaunchCheck(config, mode, monitor); + } + + @Override + public void launch(ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { + + if (mode.equals(ILaunchManager.RUN_MODE) || mode.equals(ILaunchManager.DEBUG_MODE)) { + + // NOTE: The modified working copy of launch configuration cannot be passed directly + // to the preferred delegate because in this case the LaunchHistory will not work + // properly (and the rerun last launched configuration action will fail). So we + // just modify the existing configuration and revert all the changes back after + // the launch is done. + + try { + // Changes launch configuration a bit and redirect it to the preferred C/C++ Application Launch delegate + updatedLaunchConfiguration(config); + getPreferredDelegate(config, mode).launch(config, mode, launch, monitor); + } + finally { + revertChangedToLaunchConfiguration(config); + } + activateTestingView(); + } + } + + /** + * Revert the changes to launch configuration previously made with + * updatedLaunchConfigurationAttribute(). + * + * @param config launch configuration to revert + */ + private void revertChangedToLaunchConfiguration(ILaunchConfiguration config) throws CoreException { + ILaunchConfigurationWorkingCopy configWC = config.getWorkingCopy(); + for (Map.Entry changeEntry : changesToLaunchConfiguration.entrySet()) { + configWC.setAttribute(changeEntry.getKey(), changeEntry.getValue()); + } + configWC.doSave(); + changesToLaunchConfiguration.clear(); + } + + /** + * Saves the current value of the specified attribute (to be reverted later) + * and update its value in launch configuration. + * + * @param config launch configuration which attribute should be updated + * @param attributeName attribute name + * @param value new value of the specified attribute + */ + private void updatedLaunchConfigurationAttribute(ILaunchConfigurationWorkingCopy config, String attributeName, String value) throws CoreException { + changesToLaunchConfiguration.put(attributeName, config.getAttribute(attributeName, "")); //$NON-NLS-1$ + config.setAttribute(attributeName, value); + } + + /** + * Makes the necessary changes to the launch configuration before passing it + * to the underlying delegate. Currently, updates the program arguments with + * the value that was obtained from Tests Runner provider plug-in. + * + * @param config launch configuration + */ + private void updatedLaunchConfiguration(ILaunchConfiguration config) throws CoreException { + changesToLaunchConfiguration.clear(); + ILaunchConfigurationWorkingCopy configWC = config.getWorkingCopy(); + setProgramArguments(configWC); + configWC.doSave(); + } + + /** + * Updates the program arguments with the value that was obtained from Tests + * Runner provider plug-in. + * + * @param config launch configuration + */ + private void setProgramArguments(ILaunchConfigurationWorkingCopy config) throws CoreException { + List packedTestsFilter = config.getAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_FILTER, Collections.EMPTY_LIST); + String [][] testsFilter = TestPathUtils.unpackTestPaths(packedTestsFilter.toArray(new String[packedTestsFilter.size()])); + + // Configure test module run parameters with a Tests Runner + String[] params = null; + try { + params = getTestsRunner(config).getAdditionalLaunchParameters(testsFilter); + + } catch (TestingException e) { + throw new CoreException( + new Status( + IStatus.ERROR, TestsRunnerPlugin.getUniqueIdentifier(), + e.getLocalizedMessage(), null + ) + ); + } + + // Rewrite ATTR_PROGRAM_ARGUMENTS attribute of launch configuration + if (params != null && params.length >= 1) { + StringBuilder sb = new StringBuilder(); + sb.append(config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, "")); //$NON-NLS-1$ + for (String param : params) { + sb.append(' '); + sb.append(param); + } + updatedLaunchConfigurationAttribute(config, ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, sb.toString()); + } + } + + /** + * Resolves Tests Runner provider plug-in interface by the value written in + * launch configuration. + * + * @param config launch configuration + */ + private ITestsRunnerProvider getTestsRunner(ILaunchConfiguration config) throws CoreException { + TestsRunnerProviderInfo testsRunnerProviderInfo = TestsRunnerPlugin.getDefault().getTestsRunnerProvidersManager().getTestsRunnerProviderInfo(config); + if (testsRunnerProviderInfo == null) { + throw new CoreException( + new Status( + IStatus.ERROR, TestsRunnerPlugin.getUniqueIdentifier(), + LauncherMessages.BaseTestsLaunchDelegate_invalid_tests_runner, null + ) + ); + } + ITestsRunnerProvider testsRunnerProvider = testsRunnerProviderInfo.instantiateTestsRunnerProvider(); + if (testsRunnerProvider == null) { + throw new CoreException( + new Status( + IStatus.ERROR, TestsRunnerPlugin.getUniqueIdentifier(), + LauncherMessages.BaseTestsLaunchDelegate_tests_runner_load_failed, null + ) + ); + } + return testsRunnerProvider; + } + + /** + * Resolves the preferred launch delegate for the specified configuration to + * launch C/C++ Local Application in the specified mode. The preferred + * launch delegate ID is taken from getPreferredDelegateId(). + * + * @param config launch configuration + * @param mode mode + * @return launch delegate + */ + @SuppressWarnings("unchecked") + private ILaunchConfigurationDelegate2 getPreferredDelegate(ILaunchConfiguration config, String mode) throws CoreException { + ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfigurationType localCfg = + launchMgr.getLaunchConfigurationType(ICDTLaunchConfigurationConstants.ID_LAUNCH_C_APP); + Set modes = config.getModes(); + modes.add(mode); + String preferredDelegateId = getPreferredDelegateId(); + for (ILaunchDelegate delegate : localCfg.getDelegates(modes)) { + if (preferredDelegateId.equals(delegate.getId())) { + return (ILaunchConfigurationDelegate2) delegate.getDelegate(); + } + } + return null; + } + + /** + * Returns the launch delegate id which should be used to redirect the + * launch. + * + * @return launch delegate ID + */ + public abstract String getPreferredDelegateId(); + + /** + * Activates the view showing testing results. + */ + private void activateTestingView() { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + IWorkbenchWindow activeWindow = TestsRunnerPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow(); + IViewPart view = activeWindow.getActivePage().showView(ITestsRunnerConstants.TESTS_RUNNER_RESULTS_VIEW_ID); + TestsRunnerPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().activate(view); + } catch (PartInitException e) { + TestsRunnerPlugin.log(e); + } + } + }); + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerConstants.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerConstants.java new file mode 100644 index 00000000000..948e4e685f5 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerConstants.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2012 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.launcher; + +/** + * Constants used for attributes in CDT Tests Runner launch configurations. + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface ITestsRunnerConstants { + + /** + * Tests Runner launch configuration type. + */ + public static final String LAUNCH_CONFIGURATION_TYPE_ID = "org.eclipse.cdt.testsrunner.launch.CTestsRunner"; //$NON-NLS-1$ + + /** + * Specifies the default launch delegate for a Tests Run session. + */ + public static final String PREFERRED_RUN_TESTS_LAUNCH_DELEGATE = "org.eclipse.cdt.testsrunner.launch.runTests"; //$NON-NLS-1$ + + /** + * Specifies the default launch delegate for a Tests Debug session. + */ + public static final String PREFERRED_DEBUG_TESTS_LAUNCH_DELEGATE = "org.eclipse.cdt.testsrunner.launch.dsf.runTests"; //$NON-NLS-1$ + + /** + * Specifies the ID of the Tests Runner main view for browsing results. + */ + public static final String TESTS_RUNNER_RESULTS_VIEW_ID = "org.eclipse.cdt.testsrunner.resultsview"; //$NON-NLS-1$ +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProvider.java new file mode 100644 index 00000000000..4f6ceb049be --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProvider.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.launcher; + +import java.io.InputStream; + +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.TestingException; + + +/** + * The interface for a Tests Runner provider plug-in. + * + *

+ * Clients may implement this interface. + *

+ */ +public interface ITestsRunnerProvider { + + /** + * Returns the list of automatically generated parameters that should be + * passed to test module for launching. Usually there are parameters to + * configure test module output format and content. If testPaths is not + * null, it contains the paths to the test suites and test + * cases that should be run during the testing process, so the proper + * filters should be generated too. + * + * @param testPaths the array of test paths + * @return parameters list + * @throws TestingException if test parameters cannot be generated + */ + public String[] getAdditionalLaunchParameters(String[][] testPaths) throws TestingException; + + /** + * Starts the processing of testing results by Tests Runner Plug-in. The + * input data are provided via the stream. They should be converted to the + * commands for the Model Updater. + * + * @param modelUpdater model updater instance + * @param inputStream test model output or error data stream + * @throws TestingException if there are errors during the testing process + * or in data stream + */ + public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException; + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProviderInfo.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProviderInfo.java new file mode 100644 index 00000000000..37272797d48 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProviderInfo.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.launcher; + +/** + * Describes the Tests Runner input provider plug-in, its requirements and + * features provided. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestsRunnerProviderInfo { + + /** + * Returns the user readable name of the Tests Runner provider plug-in. + * + * @return readable name + */ + public String getName(); + + /** + * Returns the unique ID of the Tests Runner provider plug-in. + * + * @return unique id + */ + public String getId(); + + /** + * Returns the short description of the Tests Runner provider plug-in. + * + * @return short description + */ + public String getDescription(); + + /** + * Returns whether Tests Runner provider plug-in allows to add a filter for + * running a few custom test cases or test suites at a time (e.g. Google + * Test and Qt Test allow it, but Boost.Test doesn't). + * + * @return whether multiple filter is supported + */ + public boolean isAllowedMultipleTestFilter(); + + /** + * Returns whether Tests Runner provider plug-in requires to handle standard + * output stream of the testing process. + * + * @return whether output stream is required + */ + public boolean isOutputStreamRequired(); + + /** + * Returns whether Tests Runner provider plug-in requires to handle standard + * error stream of the testing process. + * + * @return whether error stream is required + */ + public boolean isErrorStreamRequired(); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/IModelVisitor.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/IModelVisitor.java new file mode 100644 index 00000000000..5bf196610fd --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/IModelVisitor.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Interface to the visitor through the test model. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IModelVisitor { + + public void visit(ITestSuite testSuite); + + public void leave(ITestSuite testSuite); + + public void visit(ITestCase testCase); + + public void leave(ITestCase testCase); + + public void visit(ITestMessage testMessage); + + public void leave(ITestMessage testMessage); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestCase.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestCase.java new file mode 100644 index 00000000000..8aea7d533c9 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestCase.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Interface to the test case (test) of the test hierarchy. + * + * Test cases stores the name, status, testing time and messages. + * Also has the reference to the parent test suite (if any). + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestCase extends ITestItem { + + /** + * Returns test messages that were produced during the test case running. + * + * @return array of test messages + */ + public ITestMessage[] getTestMessages(); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestItem.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestItem.java new file mode 100644 index 00000000000..92d3d46ab8b --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestItem.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Base interface to the structural item of test hierarchy (test suite or test + * case). + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestItem { + + /** + * Represents status of the test item. + * + * @note Order of values is significant (cause enumeration values comparison + * is necessary) + */ + public enum Status { + NotRun, + Skipped, + Passed, + Failed, + Aborted; + + public boolean isError() { + return (this == Failed) || (this == Aborted); + } + } + + /** + * @return name of the test item. + */ + public String getName(); + + /** + * Returns status of the test item. + * For test case it is its own status. + * For test suite it is the greatest status of all its children. + * + * @return test item status + */ + public Status getStatus(); + + /** + * Returns execution time (in milliseconds) of the test item. + * For test case it is its own execution time. + * For test suite it is the sum of execution time of all its children. + * + * @return item execution time (in milliseconds) + */ + public int getTestingTime(); + + /** + * Returns parent of the current test item or null if not available + * (e.g. it is a root test suite). + * + * @return parent or null + */ + public ITestSuite getParent(); + + /** + * Returns true if test item has children. + * Always returns false for test cases. + * + * @return true if has children + */ + public boolean hasChildren(); + + /** + * Returns all the children of the test item. + * For test case always returns empty array. + * For test suite returns all child test suites and test cases. + * + * @return array of test item children + */ + public ITestItem[] getChildren(); + + /** + * Visitor pattern support for the tests hierarchy. + * + * @param visitor - any object that supports visitor interface + */ + public void visit(IModelVisitor visitor); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestLocation.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestLocation.java new file mode 100644 index 00000000000..133d15bf30d --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestLocation.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Describes the location of the test object. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestLocation { + + /** + * Returns the file name in which testing object is located. + * + * @return file name + */ + public String getFile(); + + /** + * Returns the line number on which testing object is located. + * + * @return line number + */ + public int getLine(); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestMessage.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestMessage.java new file mode 100644 index 00000000000..60ba09219c9 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestMessage.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Describes the message that was produced during the testing process. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestMessage { + + /** + * The level of the test message. + */ + public enum Level { + Info(ModelMessages.MessageLevel_info), + Message(ModelMessages.MessageLevel_message), + Warning(ModelMessages.MessageLevel_warning), + Error(ModelMessages.MessageLevel_error), + FatalError(ModelMessages.MessageLevel_fatal_error), + Exception(ModelMessages.MessageLevel_exception); + + String stringRepr; + + Level(String stringRepr) { + this.stringRepr = stringRepr; + } + + @Override + public String toString() { + return stringRepr; + } + } + + /** + * Returns the location of the test message. + * + * @return message location + */ + public ITestLocation getLocation(); + + /** + * Returns the level of the test message. + * + * @return message level + */ + public Level getLevel(); + + /** + * Returns the text of the test message. + * + * @return message text + */ + public String getText(); + + /** + * Visitor pattern support for the tests hierarchy. + * + * @param visitor - any object that supports visitor interface + */ + public void visit(IModelVisitor visitor); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelAccessor.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelAccessor.java new file mode 100644 index 00000000000..8a797c74234 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelAccessor.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Provides an access to the tests model. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestModelAccessor { + + /** + * Checks whether the specified testing item (case or suite) is running now. + * + * @param item the interested item + * @return whether the item is running now + */ + public boolean isCurrentlyRunning(ITestItem item); + + /** + * Provides access to the root test suite. + * + * @return root test suite + */ + public ITestSuite getRootSuite(); + + /** + * Adds the given listener to this registered listeners collection. + * Has no effect if an identical listener is already registered. + * + * @param listener the listener to add + */ + public void addChangesListener(ITestingSessionListener listener); + + /** + * Removes the given listener from registered listeners collection. + * Has no effect if the listener is not already registered. + * + * @param listener the listener to remove + */ + public void removeChangesListener(ITestingSessionListener listener); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelUpdater.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelUpdater.java new file mode 100644 index 00000000000..6cc419318ab --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelUpdater.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * The interface to easily build or update testing model. + * It is intended to use from the Tests Runner provider plug-in. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestModelUpdater { + + /** + * Specifies that a new test suite has been started. + * + * @param name the name of the started test suite + */ + public void enterTestSuite(String name); + + /** + * Specifies that the last test suite has been finished. + * Automatically exists from the currently running test case (if any). + */ + public void exitTestSuite(); + + /** + * Specifies that a new test case has been started. + * + * @param name the name of the started test case + */ + public void enterTestCase(String name); + + /** + * Sets the status of the currently running test case. + * The exception is thrown if no test case is running. + * + * @param status new test status + */ + public void setTestStatus(ITestItem.Status status); + + /** + * Sets the execution time of the currently running test case. + * If the execution time has already been set, it will be overridden. + * The exception is thrown if no test case is running. + * + * @param testingTime test execution time + */ + public void setTestingTime(int testingTime); + + /** + * Specifies that the currently running test case has been finished. + * The test execution time is set if Tests Runner provider plug-in + * requires time measurement. + */ + public void exitTestCase(); + + /** + * Add a new testing message connected to the currently running test case. + * + * @param file message file name + * @param line message line number + * @param level message level + * @param text message text + * + * @note If file name is null or empty or if line number is + * negative or 0 then message location will not be set. + */ + public void addTestMessage(String file, int line, ITestMessage.Level level, String text); + + + /** + * Access the top most currently running test suite object. + * + * @return top most test suite + */ + public ITestSuite currentTestSuite(); + + /** + * Access the currently running test case object. + * + * @return top most test case + */ + public ITestCase currentTestCase(); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestSuite.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestSuite.java new file mode 100644 index 00000000000..b2db06c5945 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestSuite.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Interface to the test suite of the tests hierarchy. + * Test suites group the test cases and the other test suites. + * They also provides group operations (e.g. status or execution time access). + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestSuite extends ITestItem { +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSession.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSession.java new file mode 100644 index 00000000000..fee30898605 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSession.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo; +import org.eclipse.debug.core.ILaunch; + + +/** + * Stores the information about tests running. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestingSession { + + /** + * Returns the count of already finished tests. + * + * @return already finished tests count + */ + public int getCurrentCounter(); + + /** + * Returns the total tests count (if available). + * + * @note Usually testing frameworks do not provide the information about + * total tests count (at least Boost.Test, Google Test and Qt Test do not). + * So the total tests count from previous launch of the same test module is + * used instead. That is why, it is unavailable for the first run and it may + * be not accurate. When testing is finished the total tests count is + * updated to the accurate value. + * + * @return total tests count or -1 if unavailable + */ + public int getTotalCounter(); + + /** + * Returns the count tests with the specified status at the moment. + * + * @note Tests count with the specified status may change if testing session + * is not terminated. + * + * @param status the required status + * @return tests count with status 'status' + */ + public int getCount(ITestItem.Status status); + + /** + * Returns whether the testing session contains errors at the moment. + * Testing session may contain errors if one of its tests failed or if there + * were some errors during tests running (e.g. test module cannot be + * launched or output parsing failed). + * + * @return whether the testing session contains errors + */ + public boolean hasErrors(); + + /** + * Returns whether the testing session was stopped by user. + * + * @note Testing session is not considered as stopped when it was terminated + * by the ILaunch.terminate() method (e.g. when user clicks on + * 'Stop' button of the 'Console' or 'Debug' view). In this case it will be + * considered as finished (probably, with errors cause not all output was + * obtained from launched process). To stop testing session properly the + * stop() method should be used. + * + * @return whether the testing session was stopped + */ + public boolean wasStopped(); + + /** + * Returns whether the testing session has been finished (with or without + * errors). + * + * @return whether the testing session has been finished + */ + public boolean isFinished(); + + /** + * Returns the testing model accessor that is associated with this session. + * + * @return testing model accessor + */ + public ITestModelAccessor getModelAccessor(); + + /** + * Returns the launch that is associated with this testing session. + * + * @return launch + */ + public ILaunch getLaunch(); + + /** + * Returns the information about the tests runner which was used to launch + * this testing session. + * + * @return tests runner information + */ + public ITestsRunnerProviderInfo getTestsRunnerProviderInfo(); + + /** + * Returns the current status message for the current testing session. It + * may contain error, some session information or simple statistics. + * + * @return text status of the testing session + */ + public String getStatusMessage(); + + /** + * Returns the name of the current testing session. Usually it contains + * launch configuration name with some additional information. + * + * @return testing session name + */ + public String getName(); + + /** + * Stops the current session with a special status setting. Does nothing if + * the launched process of testing session has already been terminated or + * cannot been terminated. + */ + public void stop(); + +} + diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSessionListener.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSessionListener.java new file mode 100644 index 00000000000..b75b34c8d4d --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSessionListener.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +/** + * Testing session listener is notified of testing process going. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ITestingSessionListener { + + /** + * Notifies the listener that the new test suite running is started. + * + * @param testSuite the started test suite + */ + public void enterTestSuite(ITestSuite testSuite); + + /** + * Notifies the listener that the test suite running is finished. + * + * @param testSuite the finished test suite + */ + public void exitTestSuite(ITestSuite testSuite); + + /** + * Notifies the listener that the new test case running is started. + * + * @param testCase the started test case + */ + public void enterTestCase(ITestCase testCase); + + /** + * Notifies the listener that the test case running is finished. + * + * @param testCase the finished test case + */ + public void exitTestCase(ITestCase testCase); + + /** + * Notifies the listener that the children of the test suite were updated. + * + * @param testSuite the test suite which require children update + */ + public void childrenUpdate(ITestSuite testSuite); + + /** + * Notifies the listener that the testing process is started. + */ + public void testingStarted(); + + /** + * Notifies the listener that the testing process is finished. + */ + public void testingFinished(); + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.java new file mode 100644 index 00000000000..eb1f39edf37 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + +import org.eclipse.osgi.util.NLS; + +public class ModelMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.model.ModelMessages"; //$NON-NLS-1$ + public static String MessageLevel_error; + public static String MessageLevel_exception; + public static String MessageLevel_fatal_error; + public static String MessageLevel_info; + public static String MessageLevel_message; + public static String MessageLevel_warning; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, ModelMessages.class); + } + + private ModelMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.properties new file mode 100644 index 00000000000..05dfe24e336 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.properties @@ -0,0 +1,16 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Anton Gorenkov - Initial implementation +############################################################################### +MessageLevel_error=Error +MessageLevel_exception=Exception +MessageLevel_fatal_error=Fatal error +MessageLevel_info=Info +MessageLevel_message=Message +MessageLevel_warning=Warning diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/TestingException.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/TestingException.java new file mode 100644 index 00000000000..5e3c4716ada --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/TestingException.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.model; + + +/** + * Represents a failure in the Tests Runner operations. + */ +public class TestingException extends Exception { + + /** + * Constructs an exception with the given descriptive message. + * + * @param msg Description of the occurred exception. + */ + public TestingException(String msg) { + super(msg); + } + +} From 4a8860255eea49dae2ec96d302088b39bd80f3b5 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Wed, 18 Apr 2012 11:56:43 -0400 Subject: [PATCH 10/13] Hide the new new project wizard. Likely to be deferred to Kepler. --- core/org.eclipse.cdt.ui/plugin.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 97ad0f894f8..2923254b523 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -455,7 +455,7 @@ %Cproject.desc - - + From 1f83e4aa213209926b082cc53db587314d1d9f0b Mon Sep 17 00:00:00 2001 From: Alex Ruiz Date: Wed, 18 Apr 2012 12:50:11 -0700 Subject: [PATCH 11/13] Bug 372551. Codan support for writing checkers that invoke external tools. Change-Id: Ia5cfd24d54ec6e67e08f24a367a6bc689ae407d0 Reviewed-on: https://git.eclipse.org/r/5586 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../META-INF/MANIFEST.MF | 12 +- .../eclipse/cdt/codan/core/cxx/Activator.java | 36 ++- .../AbstractExternalToolBasedChecker.java | 214 ++++++++++++++++++ .../core/cxx/externaltool/ArgsSeparator.java | 98 ++++++++ .../externaltool/ConfigurationSettings.java | 79 +++++++ .../IInvocationParametersProvider.java | 28 +++ .../cxx/externaltool/InvocationFailure.java | 38 ++++ .../externaltool/InvocationParameters.java | 88 +++++++ .../InvocationParametersProvider.java | 38 ++++ .../SingleConfigurationSetting.java | 80 +++++++ .../internal/externaltool/ArgsSetting.java | 41 ++++ .../cxx/internal/externaltool/Command.java | 34 +++ .../internal/externaltool/CommandBuilder.java | 57 +++++ .../externaltool/ExternalToolInvoker.java | 98 ++++++++ .../cxx/internal/externaltool/Messages.java | 26 +++ .../internal/externaltool/Messages.properties | 13 ++ .../internal/externaltool/PathSetting.java | 42 ++++ .../cxx/externaltool/ArgsSeparatorTest.java | 52 +++++ .../META-INF/MANIFEST.MF | 3 +- codan/org.eclipse.cdt.codan.core/plugin.xml | 1 + .../schema/checkerEnablement.exsd | 106 +++++++++ .../cdt/codan/core/model/AbstractChecker.java | 11 +- .../codan/core/model/CheckerLaunchMode.java | 25 +- .../cdt/codan/core/model/IChecker.java | 3 + .../param/SharedRootProblemPreference.java | 26 +++ .../codan/internal/core/CheckersRegistry.java | 42 +++- .../cdt/codan/internal/core/CodanBuilder.java | 3 +- .../core/ICheckerEnablementVerifier.java | 30 +++ .../org.eclipse.cdt.codan.examples/.classpath | 2 +- .../.settings/org.eclipse.jdt.core.prefs | 12 +- .../META-INF/MANIFEST.MF | 2 +- .../OSGI-INF/l10n/bundle.properties | 13 +- .../org.eclipse.cdt.codan.examples/plugin.xml | 49 ++++ .../checkers/cppcheck/CppcheckChecker.java | 69 ++++++ .../cppcheck/CppcheckOutputParser.java | 54 +++++ .../examples/checkers/cppcheck/Messages.java | 26 +++ .../checkers/cppcheck/Messages.properties | 11 + .../examples/checkers/cppcheck/Severity.java | 50 ++++ .../META-INF/MANIFEST.MF | 3 +- codan/org.eclipse.cdt.codan.ui/plugin.xml | 4 + .../ui/CheckerEnablementVerifier.java | 49 ++++ .../codan/internal/ui/CodanUIMessages.java | 1 + .../internal/ui/CodanUIMessages.properties | 1 + .../preferences/LaunchModesPropertyPage.java | 7 +- .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 3 +- .../schema/ErrorParser.exsd | 28 +++ .../eclipse/cdt/core/ErrorParserContext.java | 32 +++ .../eclipse/cdt/core/ErrorParserManager.java | 124 +++++++--- .../org/eclipse/cdt/core/IErrorParser3.java | 21 ++ .../eclipse/cdt/core/ProblemMarkerInfo.java | 28 +++ .../ErrorParserExtensionManager.java | 140 ++++++++++-- .../org/eclipse/cdt/internal/core/Pair.java | 35 +++ 52 files changed, 1983 insertions(+), 105 deletions(-) create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparator.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ConfigurationSettings.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/IInvocationParametersProvider.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationFailure.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParameters.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParametersProvider.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/SingleConfigurationSetting.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ArgsSetting.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Command.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/CommandBuilder.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.java create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.properties create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/PathSetting.java create mode 100644 codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparatorTest.java create mode 100644 codan/org.eclipse.cdt.codan.core/schema/checkerEnablement.exsd create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/ICheckerEnablementVerifier.java create mode 100644 codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckChecker.java create mode 100644 codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckOutputParser.java create mode 100644 codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.java create mode 100644 codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.properties create mode 100644 codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Severity.java create mode 100644 codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CheckerEnablementVerifier.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParser3.java create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Pair.java diff --git a/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF index 76a25897400..b1ce271023e 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF @@ -7,15 +7,13 @@ Bundle-Activator: org.eclipse.cdt.codan.core.cxx.Activator Require-Bundle: org.eclipse.core.runtime, org.eclipse.cdt.core, org.eclipse.cdt.codan.core, - org.eclipse.core.resources + org.eclipse.core.resources, + org.eclipse.core.filesystem Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.codan.core.cxx, - org.eclipse.cdt.codan.core.cxx.internal.model; - x-friends:="org.eclipse.cdt.codan.checkers.ui, - org.eclipse.cdt.codan.ui, - org.eclipse.cdt.codan.ui.cxx", - org.eclipse.cdt.codan.core.cxx.internal.model.cfg; - x-friends:="org.eclipse.cdt.codan.core.test", + org.eclipse.cdt.codan.core.cxx.externaltool, + org.eclipse.cdt.codan.core.cxx.internal.model;x-friends:="org.eclipse.cdt.codan.checkers.ui,org.eclipse.cdt.codan.ui,org.eclipse.cdt.codan.ui.cxx", + org.eclipse.cdt.codan.core.cxx.internal.model.cfg;x-friends:="org.eclipse.cdt.codan.core.test", org.eclipse.cdt.codan.core.cxx.model Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-Vendor: %Bundle-Vendor diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/Activator.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/Activator.java index 5251574a137..168bd3f2d0f 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/Activator.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/Activator.java @@ -32,7 +32,7 @@ public class Activator extends Plugin { /* * (non-Javadoc) - * + * * @see * org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext) */ @@ -44,7 +44,7 @@ public class Activator extends Plugin { /* * (non-Javadoc) - * + * * @see * org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) */ @@ -56,7 +56,7 @@ public class Activator extends Plugin { /** * Returns the shared instance - * + * * @return the shared instance */ public static Activator getDefault() { @@ -65,7 +65,7 @@ public class Activator extends Plugin { /** * Logs the specified status with this plug-in's log. - * + * * @param status * status to log */ @@ -74,22 +74,36 @@ public class Activator extends Plugin { } /** - * Logs an internal error with the specified throwable - * - * @param e - * the exception to be logged + * Logs an internal error with the specified {@code Throwable}. + * + * @param t + * the {@code Throwable} to be logged */ - public static void log(Throwable e) { - log(new Status(IStatus.ERROR, PLUGIN_ID, 1, "Internal Error", e)); //$NON-NLS-1$ + public static void log(Throwable t) { + log(new Status(IStatus.ERROR, PLUGIN_ID, 1, "Internal Error", t)); //$NON-NLS-1$ } /** * Logs an internal error with the specified message. - * + * * @param message * the error message to log */ public static void log(String message) { log(new Status(IStatus.ERROR, PLUGIN_ID, 1, message, null)); } + + /** + * Logs an internal error with the specified message and {@code Throwable}. + * + * @param message + * the error message to log + * @param t + * the {@code Throwable} to be logged + * + * @since 2.1 + */ + public static void log(String message, Throwable t) { + log(new Status(IStatus.ERROR, PLUGIN_ID, 1, message, t)); + } } diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java new file mode 100644 index 00000000000..6797af3a3ca --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java @@ -0,0 +1,214 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import static org.eclipse.cdt.core.ErrorParserContext.CODAN; + +import java.net.URI; + +import org.eclipse.cdt.codan.core.CodanRuntime; +import org.eclipse.cdt.codan.core.cxx.Activator; +import org.eclipse.cdt.codan.core.cxx.internal.externaltool.ExternalToolInvoker; +import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences; +import org.eclipse.cdt.codan.core.model.CheckerLaunchMode; +import org.eclipse.cdt.codan.core.model.IProblem; +import org.eclipse.cdt.codan.core.model.IProblemLocation; +import org.eclipse.cdt.codan.core.model.IProblemLocationFactory; +import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy; +import org.eclipse.cdt.codan.core.param.IProblemPreference; +import org.eclipse.cdt.codan.core.param.MapProblemPreference; +import org.eclipse.cdt.codan.core.param.RootProblemPreference; +import org.eclipse.cdt.codan.core.param.SharedRootProblemPreference; +import org.eclipse.cdt.core.ErrorParserManager; +import org.eclipse.cdt.core.IConsoleParser; +import org.eclipse.cdt.core.IMarkerGenerator; +import org.eclipse.cdt.core.ProblemMarkerInfo; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +/** + * Base class for checkers that invoke external command-line tools to perform code checking. + *

+ * A file, to be processed by this type of checker, must: + *

    + *
  1. be in the current active editor
  2. + *
  3. not have any unsaved changes
  4. + *
+ *

+ * By default, implementations of this checker are not allowed to run while the user types, since + * external tools cannot see unsaved changes. + * + * @since 2.1 + */ +public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWithProblemPreferences + implements IMarkerGenerator { + private final IInvocationParametersProvider parametersProvider; + private final ArgsSeparator argsSeparator; + private final ConfigurationSettings settings; + private final ExternalToolInvoker externalToolInvoker; + private final RootProblemPreference preferences; + + /** + * Constructor. + * @param settings user-configurable external tool configuration settings. + */ + public AbstractExternalToolBasedChecker(ConfigurationSettings settings) { + this(new InvocationParametersProvider(), new ArgsSeparator(), settings); + } + + /** + * Constructor. + * @param parametersProvider provides the parameters to pass when invoking the external tool. + * @param argsSeparator separates the arguments to pass to the external tool executable. These + * arguments are stored in a single {@code String}. + * @param settings user-configurable external tool configuration settings. + */ + public AbstractExternalToolBasedChecker(IInvocationParametersProvider parametersProvider, + ArgsSeparator argsSeparator, ConfigurationSettings settings) { + this.parametersProvider = parametersProvider; + this.argsSeparator = argsSeparator; + this.settings = settings; + externalToolInvoker = new ExternalToolInvoker(); + preferences = new SharedRootProblemPreference(); + } + + /** + * Returns {@code false} because this checker cannot run "as you type" by default. + * @return {@code false}. + */ + @Override + public boolean runInEditor() { + return false; + } + + @Override + public boolean processResource(IResource resource) { + process(resource); + return false; + } + + private void process(IResource resource) { + try { + InvocationParameters parameters = parametersProvider.createParameters(resource); + if (parameters != null) { + invokeExternalTool(parameters); + } + } catch (Throwable error) { + logResourceProcessingFailure(error, resource); + } + } + + private void invokeExternalTool(InvocationParameters parameters) throws Throwable { + updateConfigurationSettingsFromPreferences(parameters.getActualFile()); + IConsoleParser[] parsers = new IConsoleParser[] { createErrorParserManager(parameters) }; + try { + externalToolInvoker.invoke(parameters, settings, argsSeparator, parsers); + } catch (InvocationFailure error) { + handleInvocationFailure(error, parameters); + } + } + + private void updateConfigurationSettingsFromPreferences(IResource fileToProcess) { + IProblem problem = getProblemById(getReferenceProblemId(), fileToProcess); + MapProblemPreference preferences = (MapProblemPreference) problem.getPreference(); + settings.updateValuesFrom(preferences); + } + + private ErrorParserManager createErrorParserManager(InvocationParameters parameters) { + IProject project = parameters.getActualFile().getProject(); + URI workingDirectory = URIUtil.toURI(parameters.getWorkingDirectory()); + return new ErrorParserManager(project, workingDirectory, this, getParserIDs(), CODAN); + } + + /** + * @return the IDs of the parsers to use to parse the output of the external tool. + */ + protected abstract String[] getParserIDs(); + + /** + * Handles a failure reported when invoking the external tool. This implementation simply + * logs the failure. + * @param error the reported failure. + * @param parameters the parameters passed to the external tool executable. + */ + protected void handleInvocationFailure(InvocationFailure error, InvocationParameters parameters) { + logResourceProcessingFailure(error, parameters.getActualFile()); + } + + private void logResourceProcessingFailure(Throwable error, IResource resource) { + String location = resource.getLocation().toOSString(); + String msg = String.format("Unable to process resource %s", location); //$NON-NLS-1$ + Activator.log(msg, error); + } + + /** + * Returns the id of the problem used as reference to obtain this checker's preferences. All + * preferences in a external-tool-based checker are shared among its defined problems. + * @return the id of the problem used as reference to obtain this checker's preferences. + */ + protected abstract String getReferenceProblemId(); + + @Override + public void initPreferences(IProblemWorkingCopy problem) { + super.initPreferences(problem); + getLaunchModePreference(problem).enableInLaunchModes( + CheckerLaunchMode.RUN_ON_FULL_BUILD, + CheckerLaunchMode.RUN_ON_INC_BUILD, + CheckerLaunchMode.RUN_ON_FILE_SAVE, + CheckerLaunchMode.RUN_ON_DEMAND); + addPreference(problem, settings.getPath()); + addPreference(problem, settings.getArgs()); + } + + private void addPreference(IProblemWorkingCopy problem, SingleConfigurationSetting setting) { + IProblemPreference descriptor = (IProblemPreference) setting.getDescriptor(); + addPreference(problem, descriptor, setting.getDefaultValue()); + } + + @Override + protected void setDefaultPreferenceValue(IProblemWorkingCopy problem, String key, + Object defaultValue) { + MapProblemPreference map = getTopLevelPreference(problem); + map.setChildValue(key, defaultValue); + } + + @Override + public RootProblemPreference getTopLevelPreference(IProblem problem) { + RootProblemPreference map = (RootProblemPreference) problem.getPreference(); + if (map == null) { + map = preferences; + if (problem instanceof IProblemWorkingCopy) { + ((IProblemWorkingCopy) problem).setPreference(map); + } + } + return map; + } + + @Deprecated + @Override + public void addMarker(IResource file, int lineNumber, String description, int severity, + String variableName) { + addMarker(new ProblemMarkerInfo(file, lineNumber, description, severity, variableName)); + } + + @Override + public void addMarker(ProblemMarkerInfo info) { + reportProblem(getReferenceProblemId(), createProblemLocation(info), info.description); + } + + protected IProblemLocation createProblemLocation(ProblemMarkerInfo info) { + IProblemLocationFactory factory = CodanRuntime.getInstance().getProblemLocationFactory(); + return factory.createProblemLocation( + (IFile) info.file, info.startChar, info.endChar, info.lineNumber); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparator.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparator.java new file mode 100644 index 00000000000..e3b37a83094 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparator.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import java.util.ArrayList; +import java.util.List; +// import java.util.StringTokenizer; + +/** + * Separates the arguments, stored as a single {@code String}, to pass to an external tool. It uses + * an empty space as the delimiter and supports quoted arguments. + * + * @since 2.1 + */ +public class ArgsSeparator { + private static final char BACKSLASH = '\\'; + private static final char DOUBLE_QUOTE = '"'; + private static final char SINGLE_QUOTE = '\''; + private static final char SPACE = ' '; + + private static final String[] NO_ARGS = {}; + + public String[] splitArguments(String s) { + if (s == null || s.isEmpty()) { + return NO_ARGS; + } + ParserState state = ParserState.NORMAL; + StringBuilder current = new StringBuilder(); + List args = new ArrayList(); + boolean lastTokenInQuotes = false; + char previous = 0; + for (char c : s.toCharArray()) { + switch (state) { + case IN_SINGLE_QUOTE: + if (previous != BACKSLASH && c == SINGLE_QUOTE) { + lastTokenInQuotes = true; + state = ParserState.NORMAL; + } else { + previous = c; + current.append(c); + } + break; + case IN_DOUBLE_QUOTE: + if (previous != BACKSLASH && c == DOUBLE_QUOTE) { + lastTokenInQuotes = true; + state = ParserState.NORMAL; + } else { + previous = c; + current.append(c); + } + break; + default: + switch (c) { + case SINGLE_QUOTE: + if (previous != BACKSLASH) { + state = ParserState.IN_SINGLE_QUOTE; + } + break; + case DOUBLE_QUOTE: + if (previous != BACKSLASH) { + state = ParserState.IN_DOUBLE_QUOTE; + } + break; + case SPACE: + if (lastTokenInQuotes || current.length() != 0) { + args.add(current.toString()); + current.setLength(0); + } + break; + default: + previous = c; + current.append(c); + } + lastTokenInQuotes = false; + break; + } + } + if (lastTokenInQuotes || current.length() != 0) { + args.add(current.toString()); + } + if (state != ParserState.NORMAL) { + throw new IllegalArgumentException("Unbalanced quotes in " + s); //$NON-NLS-1$ + } + return args.toArray(new String[args.size()]); + } + + private static enum ParserState { + NORMAL, IN_SINGLE_QUOTE, IN_DOUBLE_QUOTE; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ConfigurationSettings.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ConfigurationSettings.java new file mode 100644 index 00000000000..a983225b6c1 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/ConfigurationSettings.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import java.io.File; + +import org.eclipse.cdt.codan.core.cxx.internal.externaltool.ArgsSetting; +import org.eclipse.cdt.codan.core.cxx.internal.externaltool.PathSetting; +import org.eclipse.cdt.codan.core.param.MapProblemPreference; + +/** + * User-configurable external tool settings. + * + * @since 2.1 + */ +public final class ConfigurationSettings { + private final PathSetting path; + private final ArgsSetting args; + private final String externalToolName; + + /** + * Constructor. + * @param externalToolName the name of the external tool. The name of the external tool is + * used in the labels of the settings' input fields. For example, assuming that the external + * tool's name is "Cppcheck", the input field for entering the path of the executable + * will have the label "Cppcheck Path". + * @param defaultPath the default path of the external tool. + * @param defaultArgs the default arguments to pass when invoking the external tool. + */ + public ConfigurationSettings(String externalToolName, File defaultPath, String defaultArgs) { + this.externalToolName = externalToolName; + this.path = new PathSetting(externalToolName, defaultPath); + this.args = new ArgsSetting(externalToolName, defaultArgs); + } + + /** + * Returns the name of the external tool, to be displayed to the user. + * @return the name of the external tool, to be displayed to the user. + */ + public String getExternalToolName() { + return externalToolName; + } + + /** + * Returns the setting that specifies the path and name of the external tool to invoke. + * @return the setting that specifies the path and name of the external tool to invoke. + */ + public SingleConfigurationSetting getPath() { + return path; + } + + /** + * Returns the setting that specifies the arguments to pass when invoking the external tool. + * @return the setting that specifies the arguments to pass when invoking the external tool. + */ + public SingleConfigurationSetting getArgs() { + return args; + } + + /** + * Updates the values of the configuration settings value with the ones stored in the given + * preference map. + * @param preferences the given preference map that may contain the values to set. + * @throws ClassCastException if any of the values to set is not of the same type as the one + * supported by a setting. + */ + public void updateValuesFrom(MapProblemPreference preferences) { + path.updateValue(preferences); + args.updateValue(preferences); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/IInvocationParametersProvider.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/IInvocationParametersProvider.java new file mode 100644 index 00000000000..6682a95305e --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/IInvocationParametersProvider.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import org.eclipse.core.resources.IResource; + +/** + * Provides the parameters to pass when invoking an external tool. + * + * @since 2.1 + */ +public interface IInvocationParametersProvider { + /** + * Creates the parameters to pass when invoking an external tool. + * @param fileToProcess the file to process. + * @return the created parameters. + * @throws Throwable if something goes wrong. + */ + InvocationParameters createParameters(IResource fileToProcess) throws Throwable; +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationFailure.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationFailure.java new file mode 100644 index 00000000000..e37a63d13f4 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationFailure.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +/** + * Indicates that invocation of an external tool failed. + * + * @since 2.1 + */ +public class InvocationFailure extends Exception { + private static final long serialVersionUID = 6727101323050538885L; + + /** + * Constructor. + * @param message the detail message. + */ + public InvocationFailure(String message) { + super(message); + } + + /** + * Constructor. + * @param message the detail message. + * @param cause the cause (which is saved for later retrieval by + * the {@link #getCause()} method.) + */ + public InvocationFailure(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParameters.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParameters.java new file mode 100644 index 00000000000..74dac3863f8 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParameters.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + +/** + * Parameters to pass when invoking an external tool. + * + * @since 2.1 + */ +public final class InvocationParameters { + private final IResource originalFile; + private final IResource actualFile; + private final String actualFilePath; + private final IPath workingDirectory; + + /** + * Constructor. + * @param originalFile the original file to process. + * @param actualFile the actual file to process. + * @param actualFilePath the path of {@code actual}, in a format that the external tool can + * understand. + * @param workingDirectory the directory where the external tool should be executed. + * @see #getOriginalFile() + * @see #getActualFile() + */ + public InvocationParameters(IResource originalFile, IResource actualFile, String actualFilePath, + IPath workingDirectory) { + this.originalFile = originalFile; + this.actualFile = actualFile; + this.actualFilePath = actualFilePath; + this.workingDirectory = workingDirectory; + } + + /** + * Returns the original file to process. This is the file that triggered execution of + * a command-line tool when saved. + * @return the original file to process. + */ + public IResource getOriginalFile() { + return originalFile; + } + + /** + * Returns the actual file to process. It may not be the same as + * {@link #getOriginalFile()}, depending on how the external tool works. + *

+ * A good example is an external tool that can only process C++ source files but not header + * files. If the original file is a header file, the checker could potentially find + * a C++ file that includes such header and use it as the actual file to process. + *

+ *

+ * We still need to keep a reference to the actual file, in order to add markers to + * the editor in case of problems found. + *

+ * @return the actual file to process. + */ + public IResource getActualFile() { + return actualFile; + } + + /** + * Returns the path of {@link #getActualFile()}, in a format the external tool can + * understand. + * @return the path of the actual file to process. + */ + public String getActualFilePath() { + return actualFilePath; + } + + /** + * Returns the directory where the external tool should be executed. + * @return the directory where the external tool should be executed. + */ + public IPath getWorkingDirectory() { + return workingDirectory; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParametersProvider.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParametersProvider.java new file mode 100644 index 00000000000..486ca98d20d --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/InvocationParametersProvider.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import org.eclipse.core.resources.IResource; + +/** + * Default implementation of {@link InvocationParameters} + * + * @since 2.1 + */ +public class InvocationParametersProvider implements IInvocationParametersProvider { + /** + * Creates the parameters to pass when invoking an external tool. + *

+ * In this implementation: + *

    + *
  • the actual file to process is the same as the original file
  • + *
  • the path of the actual file is its absolute path in the file system
  • + *
  • the working directory is {@code null}
  • + *
+ * @param fileToProcess the file to process. + * @return the created parameters. + */ + @Override + public InvocationParameters createParameters(IResource fileToProcess) { + String path = fileToProcess.getLocation().toOSString(); + return new InvocationParameters(fileToProcess, fileToProcess, path, null); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/SingleConfigurationSetting.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/SingleConfigurationSetting.java new file mode 100644 index 00000000000..8a0db6e63c0 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/SingleConfigurationSetting.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import org.eclipse.cdt.codan.core.param.IProblemPreference; +import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor; +import org.eclipse.cdt.codan.core.param.MapProblemPreference; + +/** + * Single external tool configuration setting. + * @param the type of the value this setting stores. + * + * @noextend This class is not intended to be extended by clients. + * @since 2.1 + */ +public class SingleConfigurationSetting { + private final IProblemPreferenceDescriptor descriptor; + private final T defaultValue; + private final Class valueType; + + private T value; + + /** + * Constructor. + * @param descriptor meta-data that tells the UI how to display this setting. + * @param defaultValue the setting's default value. + * @param valueType the type of the value to store (used for safe casting.) + */ + public SingleConfigurationSetting(IProblemPreferenceDescriptor descriptor, T defaultValue, + Class valueType) { + this.descriptor = descriptor; + this.defaultValue = defaultValue; + this.valueType = valueType; + } + + /** + * Returns this setting's value. + * @return this setting's value. + */ + public T getValue() { + return value; + } + + /** + * Returns the meta-data that tells the UI how to display this setting. + * @return the meta-data that tells the UI how to display this setting. + */ + public IProblemPreferenceDescriptor getDescriptor() { + return descriptor; + } + + /** + * Returns this setting's default value. + * @return this setting's default value. + */ + public T getDefaultValue() { + return defaultValue; + } + + /** + * Updates this setting's value with the one stored in the given preference map. + * @param preferences the given preference map that may contain the value to set. + * @throws ClassCastException if the value to set is not of the same type as the one supported + * by this setting. + */ + public void updateValue(MapProblemPreference preferences) { + IProblemPreference childDescriptor = preferences.getChildDescriptor(descriptor.getKey()); + if (childDescriptor != null) { + value = valueType.cast(childDescriptor.getValue()); + } + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ArgsSetting.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ArgsSetting.java new file mode 100644 index 00000000000..f4ee8ddc7e1 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ArgsSetting.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.internal.externaltool; + +import static org.eclipse.cdt.codan.core.cxx.internal.externaltool.Messages.ConfigurationSettings_args_format; +import static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_STRING; + +import org.eclipse.cdt.codan.core.cxx.externaltool.SingleConfigurationSetting; +import org.eclipse.cdt.codan.core.param.BasicProblemPreference; +import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor; + +/** + * User-configurable setting that specifies the arguments to pass when invoking the external tool. + * The arguments are stored in a single {@code String}. + */ +public class ArgsSetting extends SingleConfigurationSetting { + static final String KEY = "externalToolArgs"; //$NON-NLS-1$ + + /** + * Constructor. + * @param externalToolName the name of the external tool. The name of the external tool is + * used in the label of this setting's input field. + * @param defaultValue the default value of the setting. + */ + public ArgsSetting(String externalToolName, String defaultValue) { + super(newPreferenceDescriptor(externalToolName), defaultValue, String.class); + } + + private static IProblemPreferenceDescriptor newPreferenceDescriptor(String externalToolName) { + String label = String.format(ConfigurationSettings_args_format, externalToolName); + return new BasicProblemPreference(KEY, label, TYPE_STRING); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Command.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Command.java new file mode 100644 index 00000000000..d5e9ef8d86f --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Command.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.internal.externaltool; + +import org.eclipse.core.runtime.IPath; + +/** + * The command to execute to invoke an external tool. + */ +class Command { + private final IPath path; + private final String[] args; + + Command(IPath path, String[] args) { + this.path = path; + this.args = args; + } + + IPath getPath() { + return path; + } + + String[] getArgs() { + return args; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/CommandBuilder.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/CommandBuilder.java new file mode 100644 index 00000000000..2e128087367 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/CommandBuilder.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.internal.externaltool; + +import java.io.File; + +import org.eclipse.cdt.codan.core.cxx.externaltool.ArgsSeparator; +import org.eclipse.cdt.codan.core.cxx.externaltool.ConfigurationSettings; +import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationParameters; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * Creates the command to use to invoke an external tool. + */ +class CommandBuilder { + Command buildCommand(InvocationParameters parameters, ConfigurationSettings settings, + ArgsSeparator argsSeparator) { + IPath executablePath = executablePath(settings); + String[] args = argsToPass(parameters, settings, argsSeparator); + return new Command(executablePath, args); + } + + private IPath executablePath(ConfigurationSettings configurationSettings) { + File executablePath = configurationSettings.getPath().getValue(); + return new Path(executablePath.toString()); + } + + private String[] argsToPass(InvocationParameters parameters, + ConfigurationSettings configurationSettings, ArgsSeparator argsSeparator) { + String actualFilePath = parameters.getActualFilePath(); + String[] args = configuredArgs(configurationSettings, argsSeparator); + return addFilePathToArgs(actualFilePath, args); + } + + private String[] configuredArgs(ConfigurationSettings settings, ArgsSeparator argsSeparator) { + String args = settings.getArgs().getValue(); + return argsSeparator.splitArguments(args); + } + + private String[] addFilePathToArgs(String actualFilePath, String[] configuredArgs) { + int argCount = configuredArgs.length; + String[] allArgs = new String[argCount + 1]; + allArgs[0] = actualFilePath; + // Copy arguments + System.arraycopy(configuredArgs, 0, allArgs, 1, argCount); + return allArgs; + } +} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java new file mode 100644 index 00000000000..f8726c488cc --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/ExternalToolInvoker.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.internal.externaltool; + +import org.eclipse.cdt.codan.core.cxx.externaltool.ArgsSeparator; +import org.eclipse.cdt.codan.core.cxx.externaltool.ConfigurationSettings; +import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationFailure; +import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationParameters; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CommandLauncher; +import org.eclipse.cdt.core.ICommandLauncher; +import org.eclipse.cdt.core.IConsoleParser; +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.internal.core.ConsoleOutputSniffer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; + +/** + * Invokes an external tool to perform checks on a single file. + */ +public class ExternalToolInvoker { + private static final String[] ENV = {}; + private static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor(); + + private final CommandBuilder commandBuilder = new CommandBuilder(); + + /** + * Invokes an external tool. + * @param parameters the parameters to pass to the external tool executable. + * @param settings user-configurable settings. + * @param argsSeparator separates the arguments to pass to the external tool executable. These + * arguments are stored in a single {@code String}. + * @param parsers parse the output of the external tool. + * @throws InvocationFailure if the external tool could not be invoked or if the external tool + * itself reports that it cannot be executed (e.g. due to a configuration error). + * @throws Throwable if something else goes wrong. + */ + public void invoke(InvocationParameters parameters, ConfigurationSettings settings, + ArgsSeparator argsSeparator, IConsoleParser[] parsers) + throws InvocationFailure, Throwable { + Command command = commandBuilder.buildCommand(parameters, settings, argsSeparator); + try { + launchCommand(command, parsers, parameters); + } finally { + shutDown(parsers); + } + } + + private void launchCommand(Command command, IConsoleParser[] parsers, + InvocationParameters parameters) throws InvocationFailure, CoreException { + IProject project = parameters.getActualFile().getProject(); + IConsole c = startConsole(project); + ConsoleOutputSniffer sniffer = + new ConsoleOutputSniffer(c.getOutputStream(), c.getErrorStream(), parsers); + ICommandLauncher launcher = commandLauncher(project); + Process p = launcher.execute(command.getPath(), command.getArgs(), ENV, + parameters.getWorkingDirectory(), NULL_PROGRESS_MONITOR); + if (p == null) { + throw new InvocationFailure("Unable to launch external tool. Cause unknown."); //$NON-NLS-1$ + } + try { + p.getOutputStream().close(); + } catch (Throwable ignored) {} + try { + launcher.waitAndRead(sniffer.getOutputStream(), sniffer.getErrorStream(), NULL_PROGRESS_MONITOR); + } finally { + p.destroy(); + } + } + + private IConsole startConsole(IProject project) { + IConsole console = CCorePlugin.getDefault().getConsole(); + console.start(project); + return console; + } + + private ICommandLauncher commandLauncher(IProject project) { + ICommandLauncher launcher = new CommandLauncher(); + launcher.showCommand(true); + launcher.setProject(project); + return launcher; + } + + private void shutDown(IConsoleParser[] parsers) { + for (IConsoleParser parser : parsers) { + parser.shutdown(); + } + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.java new file mode 100644 index 00000000000..6cbca3443fa --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.internal.externaltool; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + public static String ConfigurationSettings_args_format; + public static String ConfigurationSettings_path_format; + public static String ConfigurationSettings_should_display_output; + + static { + NLS.initializeMessages(Messages.class.getName(), Messages.class); + } + + private Messages() { + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.properties b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.properties new file mode 100644 index 00000000000..577aec794fd --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/Messages.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2012 Google, Inc and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Alex Ruiz (Google) - initial API and implementation +############################################################################### +ConfigurationSettings_args_format=%s Args: +ConfigurationSettings_path_format=%s Path: +ConfigurationSettings_should_display_output=Display Output in Console diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/PathSetting.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/PathSetting.java new file mode 100644 index 00000000000..adc458a4039 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/externaltool/PathSetting.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.internal.externaltool; + +import static org.eclipse.cdt.codan.core.cxx.internal.externaltool.Messages.ConfigurationSettings_path_format; +import static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_FILE; + +import java.io.File; + +import org.eclipse.cdt.codan.core.cxx.externaltool.SingleConfigurationSetting; +import org.eclipse.cdt.codan.core.param.BasicProblemPreference; +import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor; + +/** + * User-configurable setting that specifies the path and name of an external tool's executable. + */ +public class PathSetting extends SingleConfigurationSetting { + static final String KEY = "externalToolPath"; //$NON-NLS-1$ + + /** + * Constructor. + * @param externalToolName the name of the external tool. The name of the external tool is + * used in the label of this setting's input field. + * @param defaultValue the default value of the setting. + */ + public PathSetting(String externalToolName, File defaultValue) { + super(newPreferenceDescriptor(externalToolName), defaultValue, File.class); + } + + private static IProblemPreferenceDescriptor newPreferenceDescriptor(String externalToolName) { + String label = String.format(ConfigurationSettings_path_format, externalToolName); + return new BasicProblemPreference(KEY, label, TYPE_FILE); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparatorTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparatorTest.java new file mode 100644 index 00000000000..0623c6477a3 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparatorTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import static org.junit.Assert.assertArrayEquals; +import junit.framework.TestCase; + +/** + * Tests for {@link ArgsSeparator}. + */ +@SuppressWarnings("nls") +public class ArgsSeparatorTest extends TestCase { + private ArgsSeparator separator; + + @Override + protected void setUp() { + separator = new ArgsSeparator(); + } + + public void testWithSpaceAsDelimiter() { + String[] args = separator.splitArguments("abc def ghi"); + assertArrayEquals(new String[] { "abc", "def", "ghi" }, args); + } + + public void testWithSingleQuote() { + String[] args = separator.splitArguments("abc 'def ghi' jkl"); + assertArrayEquals(new String[] { "abc", "def ghi", "jkl" }, args); + } + + public void testWithDoubleQuote() { + String[] args = separator.splitArguments("abc \"def ghi\" jkl"); + assertArrayEquals(new String[] { "abc", "def ghi", "jkl" }, args); + } + + public void testWithEscapedSingleQuote() { + String[] args = separator.splitArguments("abc 'def \\' ghi' jkl"); + assertArrayEquals(new String[] { "abc", "def \\' ghi", "jkl" }, args); + } + + public void testWithEscapedDoubleQuote() { + String[] args = separator.splitArguments("abc 'def \\\" ghi' jkl"); + assertArrayEquals(new String[] { "abc", "def \\\" ghi", "jkl" }, args); + } +} diff --git a/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF index 332b1beefa8..3690b87d098 100644 --- a/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF @@ -19,7 +19,8 @@ Export-Package: org.eclipse.cdt.codan.core, x-friends:="org.eclipse.cdt.codan.core, org.eclipse.cdt.codan.core.cxx, org.eclipse.cdt.codan.core.test, - org.eclipse.cdt.codan.ui", + org.eclipse.cdt.codan.ui, + org.eclipse.cdt.codan.ui.cxx", org.eclipse.cdt.codan.internal.core.cfg;x-friends:="org.eclipse.cdt.codan.core.cxx", org.eclipse.cdt.codan.internal.core.model; x-friends:="org.eclipse.cdt.codan.core.cxx, diff --git a/codan/org.eclipse.cdt.codan.core/plugin.xml b/codan/org.eclipse.cdt.codan.core/plugin.xml index a3af004ed87..27f4e1f212f 100644 --- a/codan/org.eclipse.cdt.codan.core/plugin.xml +++ b/codan/org.eclipse.cdt.codan.core/plugin.xml @@ -2,6 +2,7 @@ + + + + + + + + + Verifies that a checker should be executed on a given resource in a given launch mode. + + + + + + + + + + + + + + The fully qualified name of this extension point. + + + + + + + ID of the extension point (Simple ID). + + + + + + + Name of the extension point. + + + + + + + + + + + + + Specifies the implementation of ICheckerEnablementVerifier to use. + + + + + + + The implementation of ICheckerEnablementVerifier to use. + + + + + + + + + + + + + + + 2.1 + + + + + + + + + <extension point="org.eclipse.cdt.codan.core.checkerEnablement"> + <verifier class="org.eclipse.cdt.codan.internal.ui.CheckerEnablementVerifier" /> +</extension> + + + + + + + + + Plug-ins that want to extend this extension point must implement org.eclipse.cdt.codan.internal.core.ICheckerEnablementVerifier interface. + + + + + + + + + The default implementation of this extension point is org.eclipse.cdt.codan.internal.ui.CheckerEnablementVerifier. + + + + + diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java index 3767d9005d8..374355aedaa 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java @@ -11,15 +11,15 @@ *******************************************************************************/ package org.eclipse.cdt.codan.core.model; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.cdt.codan.core.CodanRuntime; import org.eclipse.cdt.codan.internal.core.CheckersRegistry; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.OperationCanceledException; -import java.util.ArrayList; -import java.util.List; - /** * Convenience implementation of IChecker interface. Has a default * implementation for common methods. @@ -37,10 +37,7 @@ public abstract class AbstractChecker implements IChecker { public AbstractChecker() { } - /** - * @return true if checker is enabled in context of resource, if returns - * false checker's "processResource" method won't be called - */ + @Deprecated @Override public boolean enabledInContext(IResource res) { return res.getType() == IResource.FILE; diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CheckerLaunchMode.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CheckerLaunchMode.java index 4f1e7559954..677bb75051c 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CheckerLaunchMode.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CheckerLaunchMode.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 Alena Laskavaia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alena Laskavaia - initial API and implementation + * Alex Ruiz (Google) + *******************************************************************************/ package org.eclipse.cdt.codan.core.model; /** @@ -12,19 +23,25 @@ package org.eclipse.cdt.codan.core.model; */ public enum CheckerLaunchMode { /** - * checker run when full build is running + * Checker runs when full build is running. */ RUN_ON_FULL_BUILD, /** - * checker run when incremental build is running + * Checker runs when incremental build is running. */ RUN_ON_INC_BUILD, /** - * checker run in editor as you type + * Checker runs when a file is saved or opened. Checker will not run if the file is an editor + * with unsaved changes. + * @since 2.1 + */ + RUN_ON_FILE_SAVE, + /** + * Checker runs in editor as you type. */ RUN_AS_YOU_TYPE, /** - * checker run when explicit command is given + * Checker runs when explicit command is given. */ RUN_ON_DEMAND, } \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java index 8ef378a970d..3f1e0b66fb6 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java @@ -72,7 +72,10 @@ public interface IChecker { * * @param resource the resource to run on. * @return true if checker should be run on this resource. + * @deprecated Replaced by {@code CheckersRegistry.isCheckerEnabled((IChecker IResource, CheckerLaunchMode)} + * and {@code ICheckerEnablementVerifier.isCheckerEnabled(IChecker IResource, CheckerLaunchMode)}. */ + @Deprecated boolean enabledInContext(IResource resource); /** diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java new file mode 100644 index 00000000000..09f6e266a80 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +/** + * Preferences that can be shared among several problems. + * + * @since 2.1 + */ +public class SharedRootProblemPreference extends RootProblemPreference { + @Override + public Object clone() { + SharedRootProblemPreference map = (SharedRootProblemPreference) super.clone(); + // alruiz: sharing the internal hash is the only way I could make this work. + map.hash = hash; + return map; + } +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java index 1e9a97d723b..ebd6a506424 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.eclipse.cdt.codan.core.CodanCorePlugin; @@ -51,7 +52,9 @@ import org.osgi.service.prefs.Preferences; public class CheckersRegistry implements Iterable, ICheckersRegistry { private static final String NAME_ATTR = "name"; //$NON-NLS-1$ private static final String ID_ATTR = "id"; //$NON-NLS-1$ - private static final String EXTENSION_POINT_NAME = "checkers"; //$NON-NLS-1$ + private static final String CLASS_ATTR = "class"; //$NON-NLS-1$ + private static final String CHECKERS_EXTENSION_POINT_NAME = "checkers"; //$NON-NLS-1$ + private static final String CHECKER_ENABLEMENT_EXTENSION_POINT_NAME = "checkerEnablement"; //$NON-NLS-1$ private static final String CHECKER_ELEMENT = "checker"; //$NON-NLS-1$ private static final String PROBLEM_ELEMENT = "problem"; //$NON-NLS-1$ private static final String CATEGORY_ELEMENT = "category"; //$NON-NLS-1$ @@ -60,19 +63,21 @@ public class CheckersRegistry implements Iterable, ICheckersRegistry { private Collection checkers = new ArrayList(); private static CheckersRegistry instance; private static boolean initialized = false; - private HashMap profiles = new HashMap(); - private HashMap> problemList = new HashMap>(); - private Map problemCheckerMapping = new HashMap(); + private final Map profiles = new HashMap(); + private final Map> problemList = new HashMap>(); + private final Map problemCheckerMapping = new HashMap(); + private final List checkerEnablementVerifiers = new ArrayList(); private CheckersRegistry() { instance = this; profiles.put(DEFAULT, new ProblemProfile(DEFAULT)); readCheckersRegistry(); + readCheckerEnablementVerifier(); initialized = true; } private void readCheckersRegistry() { - IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(CodanCorePlugin.PLUGIN_ID, EXTENSION_POINT_NAME); + IExtensionPoint ep = getExtensionPoint(CHECKERS_EXTENSION_POINT_NAME); if (ep == null) return; IConfigurationElement[] elements = ep.getConfigurationElements(); @@ -141,7 +146,7 @@ public class CheckersRegistry implements Iterable, ICheckersRegistry { name = id; IChecker checkerObj = null; try { - Object checker = configurationElement.createExecutableExtension("class"); //$NON-NLS-1$ + Object checker = configurationElement.createExecutableExtension(CLASS_ATTR); checkerObj = (IChecker) checker; addChecker(checkerObj); } catch (CoreException e) { @@ -236,6 +241,21 @@ public class CheckersRegistry implements Iterable, ICheckersRegistry { return elementValue; } + private void readCheckerEnablementVerifier() { + IExtensionPoint ep = getExtensionPoint(CHECKER_ENABLEMENT_EXTENSION_POINT_NAME); + for (IConfigurationElement ce : ep.getConfigurationElements()) { + try { + checkerEnablementVerifiers.add((ICheckerEnablementVerifier) ce.createExecutableExtension(CLASS_ATTR)); + } catch (CoreException e) { + CodanCorePlugin.log(e); + } + } + } + + private IExtensionPoint getExtensionPoint(String extensionPointName) { + return Platform.getExtensionRegistry().getExtensionPoint(CodanCorePlugin.PLUGIN_ID, extensionPointName); + } + /* * (non-Javadoc) * @@ -459,7 +479,15 @@ public class CheckersRegistry implements Iterable, ICheckersRegistry { * @param mode * @return true if the checker should run. */ - public boolean isCheckerEnabledForLaunchMode(IChecker checker, IResource resource, CheckerLaunchMode mode) { + public boolean isCheckerEnabled(IChecker checker, IResource resource, CheckerLaunchMode mode) { + if (resource.getType() != IResource.FILE) { + return false; + } + for (ICheckerEnablementVerifier verifier : checkerEnablementVerifiers) { + if (!verifier.isCheckerEnabled(checker, resource, mode)) { + return false; + } + } IProblemProfile resourceProfile = getResourceProfile(resource); Collection refProblems = getRefProblems(checker); boolean enabled = false; diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java index 4b712a0d80c..999d80790a8 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java @@ -140,8 +140,7 @@ public class CodanBuilder extends IncrementalProjectBuilder implements ICodanBui if (monitor.isCanceled()) return; if (doesCheckerSupportLaunchMode(checker, checkerLaunchMode) - && checker.enabledInContext(resource) - && chegistry.isCheckerEnabledForLaunchMode(checker, resource, checkerLaunchMode)) { + && chegistry.isCheckerEnabled(checker, resource, checkerLaunchMode)) { synchronized (checker) { try { checker.before(resource); diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/ICheckerEnablementVerifier.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/ICheckerEnablementVerifier.java new file mode 100644 index 00000000000..2a14f8fd491 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/ICheckerEnablementVerifier.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.core; + +import org.eclipse.cdt.codan.core.model.CheckerLaunchMode; +import org.eclipse.cdt.codan.core.model.IChecker; +import org.eclipse.core.resources.IResource; + +/** + * Verifies that an {@link IChecker} can be invoked. + */ +public interface ICheckerEnablementVerifier { + /** + * Indicates whether the given code checker can be invoked on the given resource in the given + * launch mode. + * @param checker the given code checker. + * @param resource the resource to be checked. + * @param mode the current launch mode. + * @return {@code true} if the given code checker can be invoked, {@code false} otherwise. + */ + public boolean isCheckerEnabled(IChecker checker, IResource resource, CheckerLaunchMode mode); +} diff --git a/codan/org.eclipse.cdt.codan.examples/.classpath b/codan/org.eclipse.cdt.codan.examples/.classpath index 64c5e31b7a2..4c62a8048e6 100644 --- a/codan/org.eclipse.cdt.codan.examples/.classpath +++ b/codan/org.eclipse.cdt.codan.examples/.classpath @@ -1,7 +1,7 @@ - + diff --git a/codan/org.eclipse.cdt.codan.examples/.settings/org.eclipse.jdt.core.prefs b/codan/org.eclipse.cdt.codan.examples/.settings/org.eclipse.jdt.core.prefs index f0c8e22e499..24697a7ea70 100644 --- a/codan/org.eclipse.cdt.codan.examples/.settings/org.eclipse.jdt.core.prefs +++ b/codan/org.eclipse.cdt.codan.examples/.settings/org.eclipse.jdt.core.prefs @@ -1,8 +1,7 @@ -#Wed Feb 23 19:44:01 EST 2011 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore @@ -70,7 +69,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.source=1.6 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 @@ -149,9 +148,12 @@ org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert diff --git a/codan/org.eclipse.cdt.codan.examples/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.examples/META-INF/MANIFEST.MF index 481af5b6365..39ffaa2d7de 100644 --- a/codan/org.eclipse.cdt.codan.examples/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.examples/META-INF/MANIFEST.MF @@ -11,7 +11,7 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.cdt.core, org.eclipse.core.resources, org.eclipse.cdt.codan.ui;bundle-version="1.0.0" -Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.codan.examples, org.eclipse.cdt.codan.examples.checkers, diff --git a/codan/org.eclipse.cdt.codan.examples/OSGI-INF/l10n/bundle.properties b/codan/org.eclipse.cdt.codan.examples/OSGI-INF/l10n/bundle.properties index fb989db8b53..430384b2808 100644 --- a/codan/org.eclipse.cdt.codan.examples/OSGI-INF/l10n/bundle.properties +++ b/codan/org.eclipse.cdt.codan.examples/OSGI-INF/l10n/bundle.properties @@ -10,4 +10,15 @@ ############################################################################### #Properties file for org.eclipse.cdt.codan.examples Bundle-Vendor = Eclipse CDT -Bundle-Name = Code Analysis Checker Examples \ No newline at end of file +Bundle-Name = Code Analysis Checker Examples + +checker.name.Cppcheck = Cppcheck +problem.description.Cppcheck.Error = Errors reported by Cppcheck (http://cppcheck.sourceforge.net/) +problem.name.Cppcheck.Error = Errors +problem.description.Cppcheck.Warning = Warnings reported by Cppcheck (http://cppcheck.sourceforge.net/) +problem.name.Cppcheck.Warning = Warnings +problem.description.Cppcheck.Syntax = Syntax problems reported by Cppcheck (http://cppcheck.sourceforge.net/) +problem.name.Cppcheck.Syntax = Syntax Problems +problem.messagePattern.Cppcheck.all = {0} + +errorparser.name.cppcheck = Cppcheck Output Parser \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.examples/plugin.xml b/codan/org.eclipse.cdt.codan.examples/plugin.xml index f12f7a82af9..dacd7a972f7 100644 --- a/codan/org.eclipse.cdt.codan.examples/plugin.xml +++ b/codan/org.eclipse.cdt.codan.examples/plugin.xml @@ -42,6 +42,42 @@ name="Search string error"> + + + + + + + + + + @@ -54,4 +90,17 @@ > + + + + + + diff --git a/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckChecker.java b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckChecker.java new file mode 100644 index 00000000000..c82a4d7f74b --- /dev/null +++ b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckChecker.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.examples.checkers.cppcheck; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.codan.core.cxx.externaltool.AbstractExternalToolBasedChecker; +import org.eclipse.cdt.codan.core.cxx.externaltool.ConfigurationSettings; +import org.eclipse.cdt.core.ProblemMarkerInfo; + +/** + * Checker that invokes Cppcheck when a C/C++ file is + * saved. + */ +public class CppcheckChecker extends AbstractExternalToolBasedChecker { + private static final String TOOL_NAME = Messages.CppcheckChecker_toolName; + private static final String EXECUTABLE_NAME = "cppcheck"; //$NON-NLS-1$ + private static final String DEFAULT_ARGS = "--enable=all"; //$NON-NLS-1$ + + private static final String DESCRIPTION_FORMAT = "[" + TOOL_NAME + "] %s"; //$NON-NLS-1$ //$NON-NLS-2$ + + private static final String ERROR_PROBLEM_ID; + + // key: severity (error, warning, etc.) - value : problem ID associated to severity + private static final Map PROBLEM_IDS = new HashMap(); + + static { + ERROR_PROBLEM_ID = addProblemId(Severity.ERROR); + addProblemId(Severity.WARNING); + addProblemId(Severity.STYLE); + } + + private static String addProblemId(Severity severity) { + String problemId = "org.eclipse.cdt.codan.checkers.cppcheck." + severity; //$NON-NLS-1$ + PROBLEM_IDS.put(severity, problemId); + return problemId; + } + + public CppcheckChecker() { + super(new ConfigurationSettings(TOOL_NAME, new File(EXECUTABLE_NAME), DEFAULT_ARGS)); + } + + @Override + protected String[] getParserIDs() { + return new String[] { "org.eclipse.cdt.codan.checkers.externaltool.CppcheckChecker" }; //$NON-NLS-1$ + } + + @Override + public void addMarker(ProblemMarkerInfo info) { + Severity severity = Severity.findSeverity(info.severity); + String description = String.format(DESCRIPTION_FORMAT, info.description); + reportProblem(PROBLEM_IDS.get(severity), createProblemLocation(info), description); + } + + @Override + protected String getReferenceProblemId() { + return ERROR_PROBLEM_ID; + } +} diff --git a/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckOutputParser.java b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckOutputParser.java new file mode 100644 index 00000000000..c9ff4ce889e --- /dev/null +++ b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/CppcheckOutputParser.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.examples.checkers.cppcheck; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.ErrorParserManager; +import org.eclipse.cdt.core.IErrorParser; +import org.eclipse.cdt.core.ProblemMarkerInfo; +import org.eclipse.core.resources.IFile; + +/** + * Parses the output of Cppcheck. + */ +public class CppcheckOutputParser implements IErrorParser { + // sample line to parse: + // + // [/src/HelloWorld.cpp:19]: (style) The scope of the variable 'i' can be reduced + // ----------1--------- -2 --3-- ------------------4------------------------- + // + // groups: + // 1: file path and name + // 2: line where problem was found + // 3: problem severity + // 4: problem description + private static Pattern pattern = Pattern.compile("\\[(.*):(\\d+)\\]:\\s*\\((.*)\\)\\s*(.*)"); //$NON-NLS-1$ + + @Override + public boolean processLine(String line, ErrorParserManager eoParser) { + Matcher matcher = pattern.matcher(line); + if (!matcher.matches()) { + return false; + } + IFile fileName = eoParser.findFileName(matcher.group(1)); + if (fileName != null) { + int lineNumber = Integer.parseInt(matcher.group(2)); + String description = matcher.group(4); + int severity = Severity.findSeverityCode(matcher.group(3)); + ProblemMarkerInfo info = new ProblemMarkerInfo(fileName, lineNumber, description, severity, null); + eoParser.addProblemMarker(info); + return true; + } + return false; + } +} diff --git a/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.java b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.java new file mode 100644 index 00000000000..b194e9f2b4f --- /dev/null +++ b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.examples.checkers.cppcheck; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + public static String CppcheckChecker_toolName; + + static { + // initialize resource bundle + Class clazz = Messages.class; + NLS.initializeMessages(clazz.getName(), clazz); + } + + private Messages() { + } +} diff --git a/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.properties b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.properties new file mode 100644 index 00000000000..8dda9c9c3ec --- /dev/null +++ b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Messages.properties @@ -0,0 +1,11 @@ +############################################################################### +# Copyright (c) 2012 Google, Inc and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Alex Ruiz (Google) - initial API and implementation +############################################################################### +CppcheckChecker_toolName=Cppcheck diff --git a/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Severity.java b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Severity.java new file mode 100644 index 00000000000..f8f91cfda46 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.examples/src/org/eclipse/cdt/codan/examples/checkers/cppcheck/Severity.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.examples.checkers.cppcheck; + +import org.eclipse.cdt.core.IMarkerGenerator; + +enum Severity { + ERROR(IMarkerGenerator.SEVERITY_ERROR_RESOURCE, "error"), //$NON-NLS-1$ + WARNING(IMarkerGenerator.SEVERITY_WARNING, "warning"), //$NON-NLS-1$ + STYLE(IMarkerGenerator.SEVERITY_INFO, "style"); //$NON-NLS-1$ + + private final int code; + private final String text; + + private Severity(int code, String text) { + this.code = code; + this.text = text; + } + + static int findSeverityCode(String text) { + for (Severity severity : values()) { + if (severity.text.equals(text)) { + return severity.code; + } + } + return STYLE.code; + } + + static Severity findSeverity(int code) { + for (Severity severity : values()) { + if (severity.code == code) { + return severity; + } + } + return STYLE; + } + + @Override + public String toString() { + return text; + } +} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF index 9517be08f76..d8980d5d46d 100644 --- a/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF @@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.ui.ide, org.eclipse.cdt.ui, org.eclipse.core.filesystem, - org.eclipse.ui.console + org.eclipse.ui.console, + org.eclipse.ui.editors Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.codan.internal.ui;x-friends:="org.eclipse.cdt.codan.ui.cxx", diff --git a/codan/org.eclipse.cdt.codan.ui/plugin.xml b/codan/org.eclipse.cdt.codan.ui/plugin.xml index 73de0766544..9dbef631ff0 100644 --- a/codan/org.eclipse.cdt.codan.ui/plugin.xml +++ b/codan/org.eclipse.cdt.codan.ui/plugin.xml @@ -238,4 +238,8 @@ + + + diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CheckerEnablementVerifier.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CheckerEnablementVerifier.java new file mode 100644 index 00000000000..114456dc469 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CheckerEnablementVerifier.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.ui; + +import org.eclipse.cdt.codan.core.model.CheckerLaunchMode; +import org.eclipse.cdt.codan.core.model.IChecker; +import org.eclipse.cdt.codan.internal.core.ICheckerEnablementVerifier; +import org.eclipse.cdt.codan.ui.CodanEditorUtility; +import org.eclipse.core.resources.IResource; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.editors.text.TextEditor; + +/** + * Default implementation of {@link ICheckerEnablementVerifier}. + */ +public class CheckerEnablementVerifier implements ICheckerEnablementVerifier { + @Override + public boolean isCheckerEnabled(IChecker checker, IResource resource, CheckerLaunchMode mode) { + if (mode != CheckerLaunchMode.RUN_ON_FILE_SAVE) { + return true; + } + for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) { + IWorkbenchPage page = window.getActivePage(); + for (IEditorReference reference : page.getEditorReferences()) { + IEditorPart editor = reference.getEditor(false); + if (!CodanEditorUtility.isResourceOpenInEditor(resource, editor)) { + continue; + } + if (editor instanceof TextEditor) { + TextEditor textEditor = (TextEditor) editor; + return !textEditor.isDirty(); + } + } + } + return false; + } +} diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.java index 0ed0f2917ce..cc8c5539b3f 100644 --- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.java +++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.java @@ -87,6 +87,7 @@ public class CodanUIMessages extends NLS { public static String LaunchModesPropertyPage_RunOnDemand; public static String LaunchModesPropertyPage_RunOnFullBuild; public static String LaunchModesPropertyPage_RunOnIncrementalBuild; + public static String LaunchModesPropertyPage_RunOnFileSave; static { NLS.initializeMessages(CodanUIMessages.class.getName(), CodanUIMessages.class); diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.properties b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.properties index 2c02d8329c7..414ab1e20e3 100644 --- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.properties +++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIMessages.properties @@ -96,3 +96,4 @@ LaunchModesPropertyPage_RunAsYouType=Run as you type LaunchModesPropertyPage_RunOnDemand=Run on demand LaunchModesPropertyPage_RunOnFullBuild=Run on full build LaunchModesPropertyPage_RunOnIncrementalBuild=Run on incremental build +LaunchModesPropertyPage_RunOnFileSave=Run on file save or open diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/preferences/LaunchModesPropertyPage.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/preferences/LaunchModesPropertyPage.java index 380862d445d..733f7c191c7 100644 --- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/preferences/LaunchModesPropertyPage.java +++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/preferences/LaunchModesPropertyPage.java @@ -37,7 +37,11 @@ public class LaunchModesPropertyPage extends FieldEditorPreferencePage { super(GRID); CheckersRegistry registry = CheckersRegistry.getInstance(); IChecker checker = registry.getCheckerForProblem(problem); - runInEditor = (checker != null) ? Checkers.canCheckerRunAsYouType(checker) : false; + if (checker != null) { + runInEditor = Checkers.canCheckerRunAsYouType(checker); + } else { + runInEditor = false; + } setPreferenceStore(prefStore); editors = new ArrayList(); } @@ -59,6 +63,7 @@ public class LaunchModesPropertyPage extends FieldEditorPreferencePage { addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FULL_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFullBuild, getFieldEditorParent())); addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_INC_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnIncrementalBuild, getFieldEditorParent())); addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_DEMAND.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnDemand, getFieldEditorParent())); + addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FILE_SAVE.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFileSave, getFieldEditorParent())); if (runInEditor) { addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_AS_YOU_TYPE.name(), CodanUIMessages.LaunchModesPropertyPage_RunAsYouType, getFieldEditorParent())); } diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index b4582b3b0ab..9f82f059e8e 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -46,7 +46,8 @@ Export-Package: org.eclipse.cdt.core, org.eclipse.cdt.debug.core, org.eclipse.cdt.managedbuilder.core, org.eclipse.cdt.make.core, - org.eclipse.cdt.make.ui", + org.eclipse.cdt.make.ui, + org.eclipse.cdt.codan.core.cxx", org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true, org.eclipse.cdt.internal.core.dom;x-internal:=true, diff --git a/core/org.eclipse.cdt.core/schema/ErrorParser.exsd b/core/org.eclipse.cdt.core/schema/ErrorParser.exsd index 0ab67eae5a2..d2709fa6939 100644 --- a/core/org.eclipse.cdt.core/schema/ErrorParser.exsd +++ b/core/org.eclipse.cdt.core/schema/ErrorParser.exsd @@ -48,6 +48,7 @@ + @@ -147,6 +148,33 @@ + + + + Use this element to specify the context where an error parser can be used. If none is specified, a default context type will be "build". + +An error parser can be assigned to more than one context type. For example, an error parser can have two "context" elements, one for "build" and one for "codan". + + + + + + + The type of context where an error parser can be used. Valid values are "build" and "codan". + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java new file mode 100644 index 00000000000..cbfefa9ba99 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserContext.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core; + +/** + * Indicates the context in which {@link org.eclipse.cdt.core.IErrorParser}s can be + * used. + * + * @since 5.4 + */ +public class ErrorParserContext { + public static final int BUILD = 1 << 0; + public static final int CODAN = 1 << 1; + + public static int getValue(String text) { + if ("build".equals(text)) { //$NON-NLS-1$ + return BUILD; + } + if ("codan".equals(text)) { //$NON-NLS-1$ + return CODAN; + } + throw new IllegalArgumentException("Unknown context value: " + text); //$NON-NLS-1$ + } +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java index ee224f5fa4c..9f39ff8e319 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java @@ -14,6 +14,8 @@ *******************************************************************************/ package org.eclipse.cdt.core; +import static org.eclipse.cdt.core.ErrorParserContext.BUILD; + import java.io.IOException; import java.io.OutputStream; import java.net.URI; @@ -73,9 +75,9 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, private final IMarkerGenerator fMarkerGenerator; private Map fErrorParsers; - private ArrayList fErrors; + private final ArrayList fErrors; - private Vector fDirectoryStack; + private final Vector fDirectoryStack; private final URI fBaseDirectoryURI; private String previousLine; @@ -147,27 +149,46 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, * @since 5.1 */ public ErrorParserManager(IProject project, URI baseDirectoryURI, IMarkerGenerator markerGenerator, String[] parsersIDs) { + this(project, baseDirectoryURI, markerGenerator, parsersIDs, BUILD); + } + + /** + * URI based constructor. + * + * @param project - project being built. + * @param baseDirectoryURI - absolute location URI of working directory of where the build is performed. + * @param markerGenerator - marker generator able to create markers. + * @param parsersIDs - array of error parsers' IDs. + * @param context - context where the error parser will be used. Valid values are defined by + * {@link ErrorParserContext}. + * @see ErrorParserContext + * @since 5.4 + */ + public ErrorParserManager(IProject project, URI baseDirectoryURI, + IMarkerGenerator markerGenerator, String[] parsersIDs, int context) { fProject = project; fMarkerGenerator = markerGenerator; fDirectoryStack = new Vector(); fErrors = new ArrayList(); - enableErrorParsers(parsersIDs); + enableErrorParsers(parsersIDs, context); - if (baseDirectoryURI != null) + if (baseDirectoryURI != null) { fBaseDirectoryURI = baseDirectoryURI; - else if (project != null) + } else if (project != null) { fBaseDirectoryURI = project.getLocationURI(); - else + } + else { fBaseDirectoryURI = org.eclipse.core.filesystem.URIUtil.toURI(System.getProperty("user.dir")); // CWD //$NON-NLS-1$ + } } - private void enableErrorParsers(String[] parsersIDs) { + private void enableErrorParsers(String[] parsersIDs, int context) { if (parsersIDs == null) { parsersIDs = ErrorParserExtensionManager.getDefaultErrorParserIds(); } fErrorParsers = new LinkedHashMap(parsersIDs.length); for (String parsersID : parsersIDs) { - IErrorParser errorParser = getErrorParserCopy(parsersID); + IErrorParser errorParser = getErrorParserCopy(parsersID, context); if (errorParser!=null) { fErrorParsers.put(parsersID, new IErrorParser[] {errorParser} ); } @@ -196,8 +217,9 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, */ @Override public URI getWorkingDirectoryURI() { - if (!fDirectoryStack.isEmpty()) + if (!fDirectoryStack.isEmpty()) { return fDirectoryStack.lastElement(); + } // Fall back to the Project Location / Build directory return fBaseDirectoryURI; @@ -214,12 +236,13 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, if (dir != null) { URI uri; URI workingDirectoryURI = getWorkingDirectoryURI(); - if (!dir.isAbsolute()) + if (!dir.isAbsolute()) { uri = URIUtil.append(workingDirectoryURI, dir.toString()); - else { + } else { uri = toURI(dir); - if (uri == null) // Shouldn't happen; error logged + if (uri == null) { return; + } } pushDirectoryURI(uri); } @@ -235,10 +258,11 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, */ public void pushDirectoryURI(URI dir) { if (dir != null) { - if (dir.isAbsolute()) + if (dir.isAbsolute()) { fDirectoryStack.addElement(dir); - else + } else { fDirectoryStack.addElement(URIUtil.makeAbsolute(dir, getWorkingDirectoryURI())); + } } } @@ -331,8 +355,9 @@ outer: } if ((types & IErrorParser2.KEEP_LONGLINES) == 0) { // long lines are not given to parsers, unless it wants it - if (lineTrimmed.length() > 1000) + if (lineTrimmed.length() > 1000) { continue; + } } // standard behavior (pre 5.1) is to trim the line String lineToParse = lineTrimmed; @@ -349,21 +374,24 @@ outer: consume = curr.processLine(lineToParse, this); } catch (Exception e){ String id = ""; //$NON-NLS-1$ - if (parser instanceof IErrorParserNamed) + if (parser instanceof IErrorParserNamed) { id = ((IErrorParserNamed)parser).getId(); + } @SuppressWarnings("nls") String message = "Errorparser " + id + " failed parsing line [" + lineToParse + "]"; CCorePlugin.log(message, e); } finally { if (fErrors.size() > 0) { - if (marker==null) + if (marker==null) { marker = fErrors.get(0); + } fErrors.clear(); } } - if (consume) + if (consume) { break outer; + } } } outputLine(line, marker); @@ -377,7 +405,9 @@ outer: */ private void outputLine(String line, ProblemMarkerInfo marker) { String l = line + "\n"; //$NON-NLS-1$ - if ( outputStream == null ) return; + if ( outputStream == null ) { + return; + } try { if ( marker != null && outputStream instanceof IErrorMarkeredOutputStream ) { IErrorMarkeredOutputStream s = (IErrorMarkeredOutputStream) outputStream; @@ -417,8 +447,9 @@ outer: */ public IFile findFileName(String partialLoc) { if (partialLoc.equals(cachedFileName) && cachedWorkingDirectory != null && - org.eclipse.core.filesystem.URIUtil.equals(getWorkingDirectoryURI(), cachedWorkingDirectory)) + org.eclipse.core.filesystem.URIUtil.equals(getWorkingDirectoryURI(), cachedWorkingDirectory)) { return cachedFile; + } // To be able to parse Windows paths on Linux systems, see bug 263977 IPath path = new Path(partialLoc.replace('\\', IPath.SEPARATOR)); @@ -433,17 +464,20 @@ outer: if (fProject != null) { IProject[] prjs = new IProject[] { fProject }; files = ResourceLookup.findFilesByName(path, prjs, false); - if (files.length == 0) + if (files.length == 0) { files = ResourceLookup.findFilesByName(path, prjs, /* ignoreCase */ true); + } } if (files == null || files.length == 0) { IProject[] prjs = ResourcesPlugin.getWorkspace().getRoot().getProjects(); files = ResourceLookup.findFilesByName(path, prjs, false); - if (files.length == 0) + if (files.length == 0) { files = ResourceLookup.findFilesByName(path, prjs, /* ignoreCase */ true); + } } - if (files.length == 1) + if (files.length == 1) { file = files[0]; + } } // Could be cygwin path @@ -471,8 +505,9 @@ outer: } else { uri = toURI(path); - if (uri == null) // Shouldn't happen; error logged + if (uri == null) { return null; + } } return findFileInWorkspace(uri); } @@ -485,12 +520,14 @@ outer: * @since 5.1 */ protected IFile findFileInWorkspace(URI uri) { - if (!uri.isAbsolute()) + if (!uri.isAbsolute()) { uri = URIUtil.makeAbsolute(uri, getWorkingDirectoryURI()); + } IFile f = ResourceLookup.selectFileForLocationURI(uri, fProject); - if (f != null && f.isAccessible()) + if (f != null && f.isAccessible()) { return f; + } return null; } @@ -581,8 +618,9 @@ outer: public void addProblemMarker(ProblemMarkerInfo problemMarkerInfo){ fErrors.add(problemMarkerInfo); fMarkerGenerator.addMarker(problemMarkerInfo); - if (problemMarkerInfo.severity == IMarkerGenerator.SEVERITY_ERROR_RESOURCE) + if (problemMarkerInfo.severity == IMarkerGenerator.SEVERITY_ERROR_RESOURCE) { hasErrors = true; + } } /** @@ -632,8 +670,9 @@ outer: */ @Override public void flush() throws IOException { - if (outputStream != null) + if (outputStream != null) { outputStream.flush(); + } } /** @@ -668,8 +707,9 @@ outer: while ((i = buffer.indexOf('\n')) != -1) { String line = buffer.substring(0, i); // get rid of any trailing '\r' - if (line.endsWith("\r")) //$NON-NLS-1$ + if (line.endsWith("\r")) { //$NON-NLS-1$ line=line.substring(0,line.length()-1); + } processLine(line); previousLine = line; buffer = buffer.substring(i + 1); // skip the \n and advance @@ -718,8 +758,9 @@ outer: String uriString = path.toString(); // On Windows "C:/folder/" -> "/C:/folder/" - if (path.isAbsolute() && uriString.charAt(0) != IPath.SEPARATOR) - uriString = IPath.SEPARATOR + uriString; + if (path.isAbsolute() && uriString.charAt(0) != IPath.SEPARATOR) { + uriString = IPath.SEPARATOR + uriString; + } return EFSExtensionManager.getDefault().createNewURIFromPath(baseURI, uriString); } @@ -829,6 +870,20 @@ outer: return ErrorParserExtensionManager.getErrorParserCopy(id, false); } + /** + * @param id - ID of error parser + * @param context - context where the error parser will be used. Valid values are defined by + * {@link ErrorParserContext}. + * @return cloned copy of error parser or {@code null}. + * Note that {@link ErrorParserNamedWrapper} returns shallow copy with the same instance + * of underlying error parser. + * @see ErrorParserContext + * @since 5.4 + */ + public static IErrorParserNamed getErrorParserCopy(String id, int context) { + return ErrorParserExtensionManager.getErrorParserCopy(id, false, context); + } + /** * @param id - ID of error parser * @return cloned copy of error parser as defined by its extension point or {@code null}. @@ -860,5 +915,12 @@ outer: */ @Override public void shutdown() { + for (IErrorParser[] parsers : fErrorParsers.values()) { + for (IErrorParser parser : parsers) { + if (parser instanceof IErrorParser3) { + ((IErrorParser3) parser).streamFinished(); + } + } + } } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParser3.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParser3.java new file mode 100644 index 00000000000..61bfda836ba --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParser3.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core; + +/** + * @since 5.4 + */ +public interface IErrorParser3 extends IErrorParser2 { + /** + * Notification that the stream of data to parse has ended. + */ + void streamFinished(); +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ProblemMarkerInfo.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ProblemMarkerInfo.java index b44f270c0b5..a81a635054b 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ProblemMarkerInfo.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ProblemMarkerInfo.java @@ -35,6 +35,14 @@ public class ProblemMarkerInfo { public IResource file; public int lineNumber; + /** + * @since 5.4 + */ + public int startChar; + /** + * @since 5.4 + */ + public int endChar; public String description; public int severity; public String variableName; @@ -53,6 +61,24 @@ public class ProblemMarkerInfo { * @param variableName - the name of the variable involved in the error if any. */ public ProblemMarkerInfo(IResource file, int lineNumber, String description, int severity, String variableName) { + this(file, lineNumber, -1,-1, description, severity, variableName); + } + + /** + * Create a new {@link ProblemMarkerInfo} object. + * + * @param file - the file where the problem has occurred. + * @param lineNumber - the line number of the problem. + * @param startChar - start char of the problem. + * @param endChar - end char of the problem. + * @param description - a description of the problem. + * @param severity - the severity of the problem, see {@link IMarkerGenerator} + * for acceptable severity values. + * @param variableName - the name of the variable involved in the error if any. + * @since 5.4 + */ + public ProblemMarkerInfo(IResource file, int lineNumber, int startChar, int endChar, + String description, int severity, String variableName) { this.file = (file != null) ? file : ResourcesPlugin.getWorkspace().getRoot(); this.lineNumber = lineNumber; this.description = description; @@ -61,6 +87,8 @@ public class ProblemMarkerInfo { this.externalPath = null ; this.type = null; this.attributes = new HashMap(); + this.startChar = -1; + this.endChar = -1; } /** diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java index df2a4d6c5bd..b3b58aa4a1a 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java @@ -11,24 +11,29 @@ package org.eclipse.cdt.internal.errorparsers; +import static org.eclipse.cdt.core.ErrorParserContext.BUILD; + import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ErrorParserManager; +import org.eclipse.cdt.core.ErrorParserContext; import org.eclipse.cdt.core.IErrorParser; import org.eclipse.cdt.core.IErrorParserNamed; import org.eclipse.cdt.core.IMarkerGenerator; import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper; import org.eclipse.cdt.core.errorparsers.RegexErrorParser; import org.eclipse.cdt.core.errorparsers.RegexErrorPattern; +import org.eclipse.cdt.internal.core.Pair; import org.eclipse.cdt.internal.core.XmlUtil; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.runtime.CoreException; @@ -56,6 +61,7 @@ public class ErrorParserExtensionManager { private static final String NONE = ""; //$NON-NLS-1$ private static final String EXTENSION_POINT_ERROR_PARSER = "org.eclipse.cdt.core.ErrorParser"; //$NON-NLS-1$ + private static final String ELEM_CONTEXT = "context"; //$NON-NLS-1$ private static final String ELEM_PLUGIN = "plugin"; //$NON-NLS-1$ private static final String ELEM_EXTENSION = "extension"; //$NON-NLS-1$ private static final String ELEM_ERRORPARSER = "errorparser"; //$NON-NLS-1$ @@ -64,7 +70,9 @@ public class ErrorParserExtensionManager { private static final String ATTR_ID = "id"; //$NON-NLS-1$ private static final String ATTR_NAME = "name"; //$NON-NLS-1$ private static final String ATTR_POINT = "point"; //$NON-NLS-1$ + private static final String ATTR_TYPE = "type"; //$NON-NLS-1$ + private static final String ATTR_REGEX = "regex"; //$NON-NLS-1$ private static final String ATTR_SEVERITY = "severity"; //$NON-NLS-1$ private static final String ATTR_FILE = "file-expr"; //$NON-NLS-1$ @@ -78,8 +86,10 @@ public class ErrorParserExtensionManager { private static final String ATTR_VALUE_INFO = "Info"; //$NON-NLS-1$ private static final String ATTR_VALUE_IGNORE = "Ignore"; //$NON-NLS-1$ - private static final LinkedHashMap fExtensionErrorParsers = new LinkedHashMap(); - private static final LinkedHashMap fAvailableErrorParsers = new LinkedHashMap(); + // Key: error parser id. Value: pair of error parser and contexts value + private static final LinkedHashMap> fExtensionErrorParsers = new LinkedHashMap>(); + // Key: error parser id. Value: pair of error parser and contexts value + private static final LinkedHashMap> fAvailableErrorParsers = new LinkedHashMap>(); private static LinkedHashMap fUserDefinedErrorParsers = null; private static List fDefaultErrorParserIds = null; @@ -112,6 +122,18 @@ public class ErrorParserExtensionManager { } } + private static class ErrorParserAndContextComparator implements Comparator> { + private static final ErrorParserComparator DELEGATE = new ErrorParserComparator(); + + @Override + public int compare(Pair pair1, + Pair pair2) { + IErrorParserNamed parser1 = pair1.first; + IErrorParserNamed parser2 = pair2.first; + return DELEGATE.compare(parser1, parser2); + } + } + static { loadUserDefinedErrorParsers(); loadDefaultErrorParserIds(); @@ -202,12 +224,13 @@ public class ErrorParserExtensionManager { * @noreference This method is not intended to be referenced by clients. */ synchronized public static void loadErrorParserExtensions() { - Set sortedErrorParsers = new TreeSet(new ErrorParserComparator()); + Set> sortedErrorParsers = + new TreeSet>(new ErrorParserAndContextComparator()); loadErrorParserExtensions(Platform.getExtensionRegistry(), sortedErrorParsers); fExtensionErrorParsers.clear(); - for (IErrorParserNamed errorParser : sortedErrorParsers) { - fExtensionErrorParsers.put(errorParser.getId(), errorParser); + for (Pair pair : sortedErrorParsers) { + fExtensionErrorParsers.put(pair.first.getId(), pair); } recalculateAvailableErrorParsers(); } @@ -218,7 +241,8 @@ public class ErrorParserExtensionManager { * @param registry - extension registry * @param errorParsers - resulting set of error parsers */ - private static void loadErrorParserExtensions(IExtensionRegistry registry, Set errorParsers) { + private static void loadErrorParserExtensions(IExtensionRegistry registry, + Set> errorParsers) { errorParsers.clear(); IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID); if (extension != null) { @@ -232,8 +256,9 @@ public class ErrorParserExtensionManager { if (cfgEl.getName().equals(ELEM_ERRORPARSER)) { IErrorParserNamed errorParser = createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl); if (errorParser!=null) { - configureErrorParser(errorParser, cfgEl); - errorParsers.add(errorParser); + Pair configured = + configureErrorParser(errorParser, cfgEl); + errorParsers.add(configured); } } } @@ -254,42 +279,50 @@ public class ErrorParserExtensionManager { List ids = new ArrayList(); if (fDefaultErrorParserIds!=null) { for (String id : fDefaultErrorParserIds) { + Pair pair = null; IErrorParserNamed errorParser = null; if (fUserDefinedErrorParsers!=null) { errorParser = fUserDefinedErrorParsers.get(id); } - if (errorParser==null) { - errorParser = fExtensionErrorParsers.get(id); + if (errorParser != null) { + pair = errorParserForBuild(errorParser); + } else { + pair = fExtensionErrorParsers.get(id); } - if (errorParser!=null) { - fAvailableErrorParsers.put(id, errorParser); + if (pair != null) { + fAvailableErrorParsers.put(id, pair); ids.add(id); } } } // then the rest in the order defined by comparator - Set sortedErrorParsers = new TreeSet(new ErrorParserComparator()); + Set> sortedErrorParsers = + new TreeSet>(new ErrorParserAndContextComparator()); if (fUserDefinedErrorParsers!=null) { for (String id : fUserDefinedErrorParsers.keySet()) { if (!ids.contains(id)) { IErrorParserNamed errorParser = fUserDefinedErrorParsers.get(id); - sortedErrorParsers.add(errorParser); + sortedErrorParsers.add(errorParserForBuild(errorParser)); } } } for (String id : fExtensionErrorParsers.keySet()) { if (!ids.contains(id)) { - IErrorParserNamed errorParser = fExtensionErrorParsers.get(id); - sortedErrorParsers.add(errorParser); + Pair pair = fExtensionErrorParsers.get(id); + sortedErrorParsers.add(pair); } } - for (IErrorParserNamed errorParser : sortedErrorParsers) { - fAvailableErrorParsers.put(errorParser.getId(), errorParser); + for (Pair pairs : sortedErrorParsers) { + fAvailableErrorParsers.put(pairs.first.getId(), pairs); } } + private static Pair errorParserForBuild(IErrorParserNamed errorParser) { + return new Pair(errorParser, ErrorParserContext.BUILD); + } + /** * Serialize error parsers in workspace level storage. * @@ -544,7 +577,8 @@ public class ErrorParserExtensionManager { * @param cfgEl - extension configuration element * @throws CoreException */ - private static void configureErrorParser(IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException { + private static Pair configureErrorParser( + IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException { String id = cfgEl.getAttribute(ATTR_ID); if (id!=null && id.length()>0) errorParser.setId(id); @@ -569,6 +603,31 @@ public class ErrorParserExtensionManager { } } } + int contexts = contextTypes(cfgEl); + return new Pair(errorParser, contexts); + } + + /** + * Returns a bit mask of contexts where an error parser can be used. Valid values for context + * are defined in {@link ErrorParserContext}. + * + * @param errorParserElement represents an "errorparser" element in the extension point + * "org.eclipse.cdt.core.ErrorParser". + * @return the contexts in which an error parser can be used, or + * {@link ErrorParserContext#BUILD BUILD} is none is specified. + * @see ErrorParserContext + */ + private static int contextTypes(IConfigurationElement errorParserElement) { + IConfigurationElement[] contextElements = errorParserElement.getChildren(ELEM_CONTEXT); + if (contextElements.length == 0) { + return BUILD; + } + int contexts = 0; + for (IConfigurationElement contextElement : contextElements) { + String contextType = contextElement.getAttribute(ATTR_TYPE); + contexts = contexts | ErrorParserContext.getValue(contextType); + } + return contexts; } /** @@ -581,7 +640,8 @@ public class ErrorParserExtensionManager { * @return internal instance of error parser */ public static IErrorParser getErrorParserInternal(String id) { - IErrorParserNamed errorParser = fAvailableErrorParsers.get(id); + Pair pair = fAvailableErrorParsers.get(id); + IErrorParserNamed errorParser = pair.first; if (errorParser instanceof ErrorParserNamedWrapper) return ((ErrorParserNamedWrapper)errorParser).getErrorParser(); return errorParser; @@ -626,14 +686,25 @@ public class ErrorParserExtensionManager { * from workspace */ public static String[] getErrorParserAvailableIds() { - return fAvailableErrorParsers.keySet().toArray(new String[0]); + return getErrorParserIds(fAvailableErrorParsers, BUILD); } /** * @return IDs of error parsers contributed through error parser extension point. */ public static String[] getErrorParserExtensionIds() { - return fExtensionErrorParsers.keySet().toArray(new String[0]); + return getErrorParserIds(fExtensionErrorParsers, BUILD); + } + + private static String[] getErrorParserIds( + Map> parsers, int context) { + List ids = new ArrayList(); + for (Map.Entry> entry : parsers.entrySet()) { + if (isInContext(entry.getValue(), context)) { + ids.add(entry.getKey()); + } + } + return ids.toArray(new String[ids.size()]); } /** @@ -690,8 +761,26 @@ public class ErrorParserExtensionManager { * shallow copy with the same instance of underlying error parser. */ public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension) { - IErrorParserNamed errorParser = isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id); + return getErrorParserCopy(id, isExtension, BUILD); + } + /** + * @param id - ID of error parser + * @param isExtension - if {@code true} get unmodified copy of error parser defined as extension + * @param context - context where the error parser will be used. Valid values are defined by + * {@link ErrorParserContext}. + * @return cloned copy of error parser. Note that {@link ErrorParserNamedWrapper} returns + * shallow copy with the same instance of underlying error parser. + * @see ErrorParserContext + */ + public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension, + int context) { + Pair pair = + isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id); + if (!isInContext(pair, context)) { + return null; + } + IErrorParserNamed errorParser = pair.first; try { if (errorParser instanceof RegexErrorParser) { return (RegexErrorParser) ((RegexErrorParser)errorParser).clone(); @@ -703,5 +792,8 @@ public class ErrorParserExtensionManager { } return errorParser; } - + + private static boolean isInContext(Pair pair, int context) { + return (pair.second & context) != 0; + } } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Pair.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Pair.java new file mode 100644 index 00000000000..3be11ee6541 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Pair.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core; + +/** + * A pair of values. + */ +public class Pair { + public final F first; + public final S second; + + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("<"); //$NON-NLS-1$ + builder.append(first); + builder.append(">, <"); //$NON-NLS-1$ + builder.append(second); + builder.append(">"); //$NON-NLS-1$ + return builder.toString(); + } +} From 357057ba1406650b2652d7119ef36b82288eac44 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Wed, 18 Apr 2012 15:44:44 -0400 Subject: [PATCH 12/13] bug 371797: Fixed bug when in legacy mode scanner discovery doesn't run after creation of a project --- .../settings/providers/ScannerDiscoveryLegacySupport.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java index 0b3f7482b13..53f77ee6fc3 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java @@ -112,7 +112,7 @@ public class ScannerDiscoveryLegacySupport { project = prjDescription.getProject(); } } - return isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription); + return !isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription); } /** @@ -125,9 +125,9 @@ public class ScannerDiscoveryLegacySupport { if (prjDescription != null) { cfgDescription = prjDescription.getActiveConfiguration(); } - return isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription); + return !isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription); } - + /** * Return list containing MBS and User provider. Used to initialize for unaware tool-chains (backward compatibility). */ From 2edf81c8a3deb13634263ed53df19098d626ba8d Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Wed, 18 Apr 2012 13:50:51 -0700 Subject: [PATCH 13/13] Bumped up PDOM version to trigger index rebuild. The rebuild is needed to fix definition of int64_t and other types that depend on attributes. --- .../parser/org/eclipse/cdt/internal/core/pdom/PDOM.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index b15b330d85b..0231bf23bae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -214,10 +214,11 @@ public class PDOM extends PlatformObject implements IPDOM { * 121.0 - Multiple variants of included header file, bug 197989. * 122.0 - Compacting strings * 123.0 - Combined file size and encoding hash code. + * 124.0 - GCC attributes and NO_RETURN flag for functions. */ - private static final int MIN_SUPPORTED_VERSION= version(123, 0); - private static final int MAX_SUPPORTED_VERSION= version(123, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(123, 0); + private static final int MIN_SUPPORTED_VERSION= version(124, 0); + private static final int MAX_SUPPORTED_VERSION= version(124, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(124, 0); private static int version(int major, int minor) { return (major << 16) + minor;