diff --git a/.gitignore b/.gitignore index 49f3cbee..ad913b3b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,4 @@ /WindowsMonitor/Monitor/x64 /WindowsMonitor/Native/Debug /WindowsMonitor/Native/Release -/WindowsMonitor/Native/x64 \ No newline at end of file +/WindowsMonitor/Native/x64 diff --git a/Bench4Q-Agent/ScenarioParameters/param1.txt b/Bench4Q-Agent/ScenarioParameters/param1.txt new file mode 100644 index 00000000..748dc5f7 --- /dev/null +++ b/Bench4Q-Agent/ScenarioParameters/param1.txt @@ -0,0 +1 @@ +row1;10;11~row2;20;21~row3,30,31~ \ No newline at end of file diff --git a/Bench4Q-Agent/Scripts/345376a7-d01c-4faa-af89-4a3e1a182048.xml b/Bench4Q-Agent/Scripts/345376a7-d01c-4faa-af89-4a3e1a182048.xml new file mode 100644 index 00000000..53e13dfa --- /dev/null +++ b/Bench4Q-Agent/Scripts/345376a7-d01c-4faa-af89-4a3e1a182048.xml @@ -0,0 +1,41 @@ + + + + + + + 1 + Get + + + url + http://www.baidu.com + + + + parameters + + + + http + + + -1 + 0 + -1 + + + 0 + + + http + Http + + + + timer + ConstantTimer + + + + \ No newline at end of file diff --git a/Bench4Q-Agent/Scripts/behaviorModel.xml b/Bench4Q-Agent/Scripts/behaviorModel.xml new file mode 100644 index 00000000..136480d0 --- /dev/null +++ b/Bench4Q-Agent/Scripts/behaviorModel.xml @@ -0,0 +1,17 @@ + + 0 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/testcase.html + + + + parameters + + + + USERBEHAVIOR + http + \ No newline at end of file diff --git a/Bench4Q-Agent/Scripts/forGoodRecord.xml b/Bench4Q-Agent/Scripts/forGoodRecord.xml new file mode 100644 index 00000000..aeb6083b --- /dev/null +++ b/Bench4Q-Agent/Scripts/forGoodRecord.xml @@ -0,0 +1,2076 @@ + + + + + + + + + 0 + Get + + + url + http://133.133.12.2:8080/bench4q-web/homepage.jsp + + + + queryParams + + + + headers + header=Accept|value= + text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|; + + + + USERBEHAVIOR + http + + + -1 + 0 + -1 + + + + + 0 + Sleep + + + time + 15 + + + TIMERBEHAVIOR + timer + + + -1 + 1 + -1 + + + + + 1 + Get + + + url + http://133.133.12.2:8080/bench4q-web/index.jsp + + + queryParams + + + + headers + header=Accept|value= + text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|; + + + + USERBEHAVIOR + http + + + 4 + 2 + -1 + + + + + 0 + Sleep + + + time + 133 + + + TIMERBEHAVIOR + timer + + + -1 + 3 + -1 + + + + + 2 + Get + + + url + http://133.133.12.2:8080/bench4q-web/css/bootstrap-cerulean.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + 3 + Get + + + url + http://133.133.12.2:8080/bench4q-web/script/login.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + 4 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/jquery-1.7.2.min.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + 5 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/jquery.i18n.properties-1.0.9.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + 6 + Get + + + url + http://133.133.12.2:8080/bench4q-web/css/charisma-app.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 4 + 2 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 5 + -1 + + + + + 0 + Sleep + + + time + 72 + + + TIMERBEHAVIOR + timer + + + -1 + 6 + -1 + + + + + 0 + Sleep + + + time + 24 + + + TIMERBEHAVIOR + timer + + + -1 + 7 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 8 + -1 + + + + + 0 + Sleep + + + time + 211 + + + TIMERBEHAVIOR + timer + + + -1 + 9 + -1 + + + + + 7 + Get + + + url + http://fonts.googleapis.com/css + + + queryParams + family=Karla|Ubuntu + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 10 + -1 + + + + + 0 + Sleep + + + time + 3 + + + TIMERBEHAVIOR + timer + + + -1 + 11 + -1 + + + + + 8 + Get + + + url + http://fonts.googleapis.com/css + + + queryParams + family=Shojumaru + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 12 + -1 + + + + + 0 + Sleep + + + time + 82 + + + TIMERBEHAVIOR + timer + + + -1 + 13 + -1 + + + + + 9 + Get + + + url + http://133.133.12.2:8080/bench4q-web/img/glyphicons-halflings.png + + + + queryParams + + + + headers + header=Accept|value= + image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 14 + -1 + + + + + 0 + Sleep + + + time + 2 + + + TIMERBEHAVIOR + timer + + + -1 + 15 + -1 + + + + + 10 + Get + + + url + http://133.133.12.2:8080/bench4q-web/i18n/i18n.properties + + + + queryParams + _=1389777175541 + + + headers + header=Content-Type|value=text/plain;charset=UTF-8|;header=Accept|value= + text/plain, */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 16 + -1 + + + + + 0 + Sleep + + + time + 10 + + + TIMERBEHAVIOR + timer + + + -1 + 17 + -1 + + + + + 11 + Get + + + url + http://133.133.12.2:8080/bench4q-web/i18n/i18n_zh.properties + + + + queryParams + _=1389777175572 + + + headers + header=Content-Type|value=text/plain;charset=UTF-8|;header=Accept|value= + text/plain, */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 18 + -1 + + + + + 0 + Sleep + + + time + 8 + + + TIMERBEHAVIOR + timer + + + -1 + 19 + -1 + + + + + 12 + Get + + + url + http://133.133.12.2:8080/bench4q-web/i18n/i18n_zh-CN.properties + + + + queryParams + _=1389777175587 + + + headers + header=Content-Type|value=text/plain;charset=UTF-8|;header=Accept|value= + text/plain, */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 20 + -1 + + + + + 0 + Sleep + + + time + 52 + + + TIMERBEHAVIOR + timer + + + -1 + 21 + -1 + + + + + 13 + Get + + + url + http://themes.googleusercontent.com/static/fonts/karla/v3/azR40LUJrT4HaWK28zHmVA.woff + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 22 + -1 + + + + + 0 + Sleep + + + time + 16442 + + + TIMERBEHAVIOR + timer + + + -1 + 23 + -1 + + + + + 14 + Get + + + url + http://themes.googleusercontent.com/static/fonts/ubuntu/v5/_xyN3apAT_yRRDeqB3sPRg.woff + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 24 + -1 + + + + + + + + + 0 + Sleep + + + time + 9 + + + TIMERBEHAVIOR + timer + + + 3 + 25 + -1 + + + + + 15 + Get + + + url + http://133.133.12.2:8080/bench4q-web/homepage.jsp + + + + queryParams + + + + headers + header=Accept|value= + text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 26 + -1 + + + + + 0 + Sleep + + + time + 25 + + + TIMERBEHAVIOR + timer + + + -1 + 27 + -1 + + + + + 16 + Get + + + url + http://133.133.12.2:8080/bench4q-web/css/bootstrap-responsive.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 17 + Get + + + url + http://133.133.12.2:8080/bench4q-web/css/noty_theme_default.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 18 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/jquery-1.8.2.min.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 19 + Get + + + url + http://133.133.12.2:8080/bench4q-web/bench4q-css/bench4q.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 20 + Get + + + url + http://133.133.12.2:8080/bench4q-web/css/jquery-ui-1.8.21.custom.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 21 + Get + + + url + http://133.133.12.2:8080/bench4q-web/css/opa-icons.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 22 + Get + + + url + http://133.133.12.2:8080/bench4q-web/css/colorbox.css + + + + queryParams + + + + headers + header=Accept|value= + text/css,*/*;q=0.1|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 23 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/jquery.cookie.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 24 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/jquery.dataTables.min.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 25 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/theme.js + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 26 + Get + + + url + http://133.133.12.2:8080/bench4q-web/script/base.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 27 + Get + + + url + http://133.133.12.2:8080/bench4q-web/script/bench4q.table.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 28 + Get + + + url + http://133.133.12.2:8080/bench4q-web/script/loadTestPlans.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 29 + Get + + + url + http://133.133.12.2:8080/bench4q-web/script/scriptTable.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 30 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/jquery-ui-1.8.21.custom.min.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 31 + Get + + + url + http://133.133.12.2:8080/bench4q-web/img/bench4q.png + + + + queryParams + + + + headers + header=Accept|value= + image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 32 + Get + + + url + http://133.133.12.2:8080/bench4q-web/js/bootstrap-dropdown.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + 36 + Get + + + url + http://133.133.12.2:8080/bench4q-web/script/home.js + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 28 + 0 + + + + + 0 + Sleep + + + time + 10 + + + TIMERBEHAVIOR + timer + + + -1 + 29 + -1 + + + + + 0 + Sleep + + + time + 25 + + + TIMERBEHAVIOR + timer + + + -1 + 30 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 31 + -1 + + + + + 0 + Sleep + + + time + 4 + + + TIMERBEHAVIOR + timer + + + -1 + 32 + -1 + + + + + 0 + Sleep + + + time + 4 + + + TIMERBEHAVIOR + timer + + + -1 + 33 + -1 + + + + + 0 + Sleep + + + time + 0 + + + TIMERBEHAVIOR + timer + + + -1 + 34 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 35 + -1 + + + + + 0 + Sleep + + + time + 6 + + + TIMERBEHAVIOR + timer + + + -1 + 36 + -1 + + + + + 0 + Sleep + + + time + 27 + + + TIMERBEHAVIOR + timer + + + -1 + 37 + -1 + + + + + 0 + Sleep + + + time + 9 + + + TIMERBEHAVIOR + timer + + + -1 + 38 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 39 + -1 + + + + + 0 + Sleep + + + time + 0 + + + TIMERBEHAVIOR + timer + + + -1 + 40 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 41 + -1 + + + + + 0 + Sleep + + + time + 36 + + + TIMERBEHAVIOR + timer + + + -1 + 42 + -1 + + + + + 0 + Sleep + + + time + 5 + + + TIMERBEHAVIOR + timer + + + -1 + 43 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 44 + -1 + + + + + 0 + Sleep + + + time + 75 + + + TIMERBEHAVIOR + timer + + + -1 + 45 + -1 + + + + + 33 + Get + + + url + http://133.133.12.2:8080/bench4q-web/img/opa-icons-blue32.png + + + + queryParams + + + + headers + header=Accept|value= + image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 46 + -1 + + + + + 0 + Sleep + + + time + 30 + + + TIMERBEHAVIOR + timer + + + -1 + 47 + -1 + + + + + 34 + Get + + + url + http://133.133.12.2:8080/bench4q-web/img/opa-icons-color32.png + + + + queryParams + + + + headers + header=Accept|value= + image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 48 + -1 + + + + + 0 + Sleep + + + time + 27 + + + TIMERBEHAVIOR + timer + + + -1 + 49 + -1 + + + + + 35 + Get + + + url + http://133.133.12.2:8080/bench4q-web/img/opa-icons-red32.png + + + + queryParams + + + + headers + header=Accept|value= + image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 50 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 51 + -1 + + + + + 0 + Sleep + + + time + 24 + + + TIMERBEHAVIOR + timer + + + -1 + 52 + -1 + + + + + 37 + Get + + + url + http://themes.googleusercontent.com/static/fonts/shojumaru/v2/pYVcIM206l3F7GUKEvtB3T8E0i7KZn-EPnyo3HZu7kw.woff + + + + queryParams + + + + headers + header=Accept|value= + */*|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/index.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 53 + -1 + + + + + 0 + Sleep + + + time + 145 + + + TIMERBEHAVIOR + timer + + + -1 + 54 + -1 + + + + + 38 + Get + + + url + http://133.133.12.2:8080/bench4q-web/img/opa-icons-green32.png + + + + queryParams + + + + headers + header=Accept|value= + image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 55 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 56 + -1 + + + + + 39 + Get + + + url + http://133.133.12.2:8080/bench4q-web/i18n/i18n.properties + + + + queryParams + _=1389777196041 + + + headers + header=Content-Type|value=text/plain;charset=UTF-8|;header=Accept|value= + text/plain, */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 57 + -1 + + + + + 0 + Sleep + + + time + 8 + + + TIMERBEHAVIOR + timer + + + -1 + 58 + -1 + + + + + 40 + Get + + + url + http://133.133.12.2:8080/bench4q-web/i18n/i18n_zh.properties + + + + queryParams + _=1389777196134 + + + headers + header=Content-Type|value=text/plain;charset=UTF-8|;header=Accept|value= + text/plain, */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 59 + -1 + + + + + 0 + Sleep + + + time + 7 + + + TIMERBEHAVIOR + timer + + + -1 + 60 + -1 + + + + + 41 + Get + + + url + http://133.133.12.2:8080/bench4q-web/i18n/i18n_zh-CN.properties + + + + queryParams + _=1389777196150 + + + headers + header=Content-Type|value=text/plain;charset=UTF-8|;header=Accept|value= + text/plain, */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 61 + -1 + + + + + 0 + Sleep + + + time + 163 + + + TIMERBEHAVIOR + timer + + + -1 + 62 + -1 + + + + + 42 + Post + + + url + http://133.133.12.2:8080/bench4q-web/loadTestPlans + + + + queryParams + + + + headers + header=Accept|value= application/json, text/javascript, + */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + bodyparameters + + + + USERBEHAVIOR + http + + + -1 + 63 + -1 + + + + + 0 + Sleep + + + time + 1 + + + TIMERBEHAVIOR + timer + + + -1 + 64 + -1 + + + + + 43 + Post + + + url + http://133.133.12.2:8080/bench4q-web/loadScript + + + queryParams + + + + headers + header=Accept|value= application/json, text/javascript, + */*; + q=0.01|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + bodyparameters + + + + USERBEHAVIOR + http + + + -1 + 65 + -1 + + + + + 0 + Sleep + + + time + 27 + + + TIMERBEHAVIOR + timer + + + -1 + 66 + -1 + + + + + 44 + Get + + + url + http://133.133.12.2:8080/bench4q-web/img/glyphicons-halflings-white.png + + + + queryParams + + + + headers + header=Accept|value= + image/webp,*/*;q=0.8|;header=Referer|value=http://133.133.12.2:8080/bench4q-web/homepage.jsp|; + + + + USERBEHAVIOR + http + + + -1 + 67 + -1 + + + + + 0 + + + http + Http + + + + timer + ConstantTimer + + + + \ No newline at end of file diff --git a/Bench4Q-Agent/Scripts/goodForBatch.xml b/Bench4Q-Agent/Scripts/goodForBatch.xml new file mode 100644 index 00000000..8be2d6e7 --- /dev/null +++ b/Bench4Q-Agent/Scripts/goodForBatch.xml @@ -0,0 +1,146 @@ + + + + + + + 1 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/testcase.html + + + + parameters + + + + http + + + 2 + 0 + -1 + + + + + 0 + Sleep + + + time + 2500 + + + timer + + + -1 + 1 + -1 + + + + + 3 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/images/3.jpg + + + + parameters + + + + http + + + 4 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/script/agentTable.js + + + + parameters + + + + http + + + 5 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/script/base.js + + + + parameters + + + + http + + + 6 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/images/1.jpg + + + + parameters + + + + http + + + 7 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/images/2.jpg + + + + parameters + + + + http + + + -1 + 2 + 0 + + + 0 + + + http + Http + + + + timer + ConstantTimer + + + + \ No newline at end of file diff --git a/Bench4Q-Agent/Scripts/goodForPage.xml b/Bench4Q-Agent/Scripts/goodForPage.xml new file mode 100644 index 00000000..12cb22e0 --- /dev/null +++ b/Bench4Q-Agent/Scripts/goodForPage.xml @@ -0,0 +1,234 @@ + + + + + + + + + 0 + Get + + + url + + http://133.133.12.3:8080/Bench4QTestCase/testcase.html + + + + parameters + + + + USERBEHAVIOR + http + + + 2 + 0 + -1 + + + + + 0 + Sleep + + + time + 230 + + + TIMERBEHAVIOR + timer + + + -1 + 1 + -1 + + + + + 1 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/script/agentTable.js + + + + parameters + + + + USERBEHAVIOR + http + + + 2 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/images/3.jpg + + + + parameters + + + + USERBEHAVIOR + http + + + 3 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/script/base.js + + + + parameters + + + + USERBEHAVIOR + http + + + 4 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/images/1.jpg + + + + parameters + + + + USERBEHAVIOR + http + + + 5 + Get + + + url + http://133.133.12.3:8080/Bench4QTestCase/images/2.jpg + + + + parameters + + + + USERBEHAVIOR + http + + + -1 + 2 + 0 + + + + + 0 + Sleep + + + time + 96 + + + TIMERBEHAVIOR + timer + + + -1 + 3 + -1 + + + + + 0 + Sleep + + + time + 3 + + + TIMERBEHAVIOR + timer + + + -1 + 4 + -1 + + + + + 0 + Sleep + + + time + 10 + + + TIMERBEHAVIOR + timer + + + -1 + 5 + -1 + + + + + 0 + Sleep + + + time + 6 + + + TIMERBEHAVIOR + timer + + + -1 + 6 + -1 + + + + + 0 + + + http + Http + + + + timer + ConstantTimer + + + + \ No newline at end of file diff --git a/Bench4Q-Agent/Scripts/testJD.xml b/Bench4Q-Agent/Scripts/testJD.xml new file mode 100644 index 00000000..f8c2d673 --- /dev/null +++ b/Bench4Q-Agent/Scripts/testJD.xml @@ -0,0 +1,66 @@ + + + + + + + + + 0 + Get + + + url + + http://www.baidu.com + + + + parameters + + + + USERBEHAVIOR + http + + + 2 + 0 + -1 + + + + + 0 + Sleep + + + time + 230 + + + TIMERBEHAVIOR + timer + + + -1 + 1 + -1 + + + + + 0 + + + http + Http + + + + timer + ConstantTimer + + + + \ No newline at end of file diff --git a/Bench4Q-Agent/StorageTest/testInput.txt b/Bench4Q-Agent/StorageTest/testInput.txt new file mode 100644 index 00000000..785f1382 --- /dev/null +++ b/Bench4Q-Agent/StorageTest/testInput.txt @@ -0,0 +1 @@ +1Get1064text/html2013-12-16T10:01:02.620+08:00httpHttp6true2013-12-16T10:01:02.614+08:00200true \ No newline at end of file diff --git a/Bench4Q-Agent/StorageTest/test_123.txt b/Bench4Q-Agent/StorageTest/test_123.txt new file mode 100644 index 00000000..30d74d25 --- /dev/null +++ b/Bench4Q-Agent/StorageTest/test_123.txt @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/Bench4Q-Agent/configure/agent-config.properties b/Bench4Q-Agent/configure/agent-config.properties new file mode 100644 index 00000000..3c09e025 --- /dev/null +++ b/Bench4Q-Agent/configure/agent-config.properties @@ -0,0 +1,3 @@ +isToSaveDetailResult=false +servePort=6565 +userDefinedParamFolder=userDefinedParams \ No newline at end of file diff --git a/Bench4Q-Agent/descriptor.xml b/Bench4Q-Agent/descriptor.xml new file mode 100644 index 00000000..ca85606d --- /dev/null +++ b/Bench4Q-Agent/descriptor.xml @@ -0,0 +1,25 @@ + + + publish + + tar.gz + + false + + + lib + false + false + runtime + + + + + target/bench4q-agent.jar + / + + + \ No newline at end of file diff --git a/Bench4Q-Agent/pom.xml b/Bench4Q-Agent/pom.xml new file mode 100644 index 00000000..b08d984e --- /dev/null +++ b/Bench4Q-Agent/pom.xml @@ -0,0 +1,124 @@ + + 4.0.0 + org.bench4q + bench4q-agent + jar + 0.0.1-SNAPSHOT + Bench4Q Agent + Bench4Q Agent + + TCSE, ISCAS + + + + junit + junit + 4.11 + test + + + org.eclipse.jetty + jetty-server + 9.1.0.RC2 + + + org.eclipse.jetty + jetty-servlet + 9.1.0.RC2 + + + org.springframework + spring-webmvc + 3.2.4.RELEASE + + + org.codehaus.jackson + jackson-core-lgpl + 1.9.13 + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.13 + + + org.apache.hadoop + hadoop-core + 1.1.2 + + + log4j + log4j + 1.2.17 + + + org.bench4q + bench4q-share + 0.0.1-SNAPSHOT + + + org.springframework + spring-core + 3.2.5.RELEASE + + + org.springframework + spring-test + 3.2.5.RELEASE + + + + commons-fileupload + commons-fileupload + 1.2 + + + + commons-io + commons-io + 2.4 + + + + + + maven-jar-plugin + + + + org.bench4q.agent.Main + true + lib/ + + + + + + maven-assembly-plugin + + + make-zip + package + + single + + + + descriptor.xml + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + bench4q-agent + + \ No newline at end of file diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/AgentServer.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/AgentServer.java new file mode 100644 index 00000000..66a95382 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/AgentServer.java @@ -0,0 +1,64 @@ +package org.bench4q.agent; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.springframework.web.servlet.DispatcherServlet; + +public class AgentServer { + private Server server; + private int port; + + private Server getServer() { + return server; + } + + private void setServer(Server server) { + this.server = server; + } + + private int getPort() { + return port; + } + + private void setPort(int port) { + this.port = port; + } + + public AgentServer(int port) { + this.setPort(port); + } + + public boolean start() { + try { + this.setServer(new Server(this.getPort())); + ServletContextHandler servletContextHandler = new ServletContextHandler(); + ServletHolder servletHolder = servletContextHandler.addServlet( + DispatcherServlet.class, "/"); + servletHolder + .setInitParameter("contextConfigLocation", + "classpath*:/org/bench4q/agent/config/application-context.xml"); + servletHolder.setInitOrder(1); + this.getServer().setHandler(servletContextHandler); + this.getServer().start(); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean stop() { + try { + if (this.getServer() != null) { + this.getServer().stop(); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } finally { + this.setServer(null); + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/Main.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/Main.java new file mode 100644 index 00000000..45c45d7b --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/Main.java @@ -0,0 +1,86 @@ +package org.bench4q.agent; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +import org.apache.log4j.Logger; + +public class Main { + private static final String CONFIG_FILE_NAME = "agent-config.properties"; + private static String DIR_PATH = "configure" + + System.getProperty("file.separator"); + private static Logger logger = Logger.getLogger(Main.class); + private static int PORT_TO_SERVE; + public static boolean IS_TO_SAVE_DETAIL; + public static String USER_DEFINED_PARAMS_FOLDER; + + static { + init(); + } + + public static void main(String[] args) { + AgentServer agentServer = new AgentServer(PORT_TO_SERVE); + agentServer.start(); + } + + public static void init() { + guardConfigureExists(); + initProperties(); + } + + private static void guardConfigureExists() { + File dirFile = new File(DIR_PATH); + if (!dirFile.exists()) { + dirFile.mkdirs(); + } + File configFile = new File(DIR_PATH + CONFIG_FILE_NAME); + if (!configFile.exists()) { + createDefaultConfig(configFile); + } + } + + private static void createDefaultConfig(File configFile) { + try { + if (configFile.createNewFile()) { + FileOutputStream outputStream = new FileOutputStream(configFile); + String content = "isToSaveDetailResult=false" + "\n" + + "servePort=6565" + "\n" + + "userDefinedParamFolder=userDefinedParams"; + outputStream.write(content.getBytes()); + outputStream.flush(); + outputStream.close(); + } + } catch (Exception e) { + } + } + + private static void initProperties() { + try { + FileInputStream inputStream = new FileInputStream(new File(DIR_PATH + + CONFIG_FILE_NAME)); + Properties properties = new Properties(); + properties.load(inputStream); + PORT_TO_SERVE = Integer.parseInt((String) properties + .get("servePort")); + IS_TO_SAVE_DETAIL = Boolean.parseBoolean((String) properties + .get("isToSaveDetailResult")); + USER_DEFINED_PARAMS_FOLDER = properties + .getProperty("userDefinedParamFolder"); + guardUserDefinedFolderExists(); + } catch (IOException e) { + logger.error("There is an error when getPortToServe!"); + } + } + + private static void guardUserDefinedFolderExists() { + File dirFile = new File(USER_DEFINED_PARAMS_FOLDER + + System.getProperty("file.separator")); + if (!dirFile.exists()) { + dirFile.mkdirs(); + } + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/HomeController.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/HomeController.java new file mode 100644 index 00000000..22d6d739 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/HomeController.java @@ -0,0 +1,49 @@ +package org.bench4q.agent.api; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.bench4q.agent.scenario.ScenarioContext; +import org.bench4q.agent.scenario.ScenarioEngine; +import org.bench4q.share.models.agent.ServerStatusModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/") +public class HomeController { + private ScenarioEngine scenarioEngine; + + private ScenarioEngine getScenarioEngine() { + return scenarioEngine; + } + + @Autowired + private void setScenarioEngine(ScenarioEngine scenarioEngine) { + this.scenarioEngine = scenarioEngine; + } + + @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }) + @ResponseBody + public ServerStatusModel index() { + ServerStatusModel serverStatusModel = new ServerStatusModel(); + serverStatusModel.setFinishedTests(new ArrayList()); + serverStatusModel.setRunningTests(new ArrayList()); + Map contexts = new HashMap( + getScenarioEngine().getRunningTests()); + for (UUID key : contexts.keySet()) { + ScenarioContext value = contexts.get(key); + if (value.isFinished()) { + serverStatusModel.getFinishedTests().add(key); + } else { + serverStatusModel.getRunningTests().add(key); + } + } + return serverStatusModel; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/PluginController.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/PluginController.java new file mode 100644 index 00000000..f903984b --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/PluginController.java @@ -0,0 +1,81 @@ +package org.bench4q.agent.api; + +import java.util.ArrayList; +import java.util.List; + +import org.bench4q.agent.plugin.BehaviorInfo; +import org.bench4q.agent.plugin.ParameterInfo; +import org.bench4q.agent.plugin.PluginInfo; +import org.bench4q.agent.plugin.PluginManager; +import org.bench4q.share.models.agent.BehaviorInfoModel; +import org.bench4q.share.models.agent.ParameterInfoModel; +import org.bench4q.share.models.agent.PluginInfoListModel; +import org.bench4q.share.models.agent.PluginInfoModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/plugin") +public class PluginController { + private PluginManager pluginManager; + + public PluginManager getPluginManager() { + return pluginManager; + } + + @Autowired + public void setPluginManager(PluginManager pluginManager) { + this.pluginManager = pluginManager; + } + + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + public PluginInfoListModel list() { + List pluginInfos = this.getPluginManager().getPluginInfo(); + PluginInfoListModel pluginInfoListModel = new PluginInfoListModel(); + pluginInfoListModel.setPlugins(new ArrayList()); + for (PluginInfo pluginInfo : pluginInfos) { + PluginInfoModel pluginInfoModel = buildPluginInfoModel(pluginInfo); + pluginInfoListModel.getPlugins().add(pluginInfoModel); + } + return pluginInfoListModel; + } + + private PluginInfoModel buildPluginInfoModel(PluginInfo pluginInfo) { + PluginInfoModel pluginInfoModel = new PluginInfoModel(); + pluginInfoModel.setName(pluginInfo.getName()); + pluginInfoModel.setParameters(new ArrayList()); + for (ParameterInfo param : pluginInfo.getParameters()) { + ParameterInfoModel model = buildParameterInfoModel(param); + pluginInfoModel.getParameters().add(model); + } + pluginInfoModel.setBehaviors(new ArrayList()); + for (BehaviorInfo behaviorInfo : pluginInfo.getBehaviors()) { + BehaviorInfoModel behaviorInfoModel = buildBehaviorInfoModel(behaviorInfo); + pluginInfoModel.getBehaviors().add(behaviorInfoModel); + } + return pluginInfoModel; + } + + private BehaviorInfoModel buildBehaviorInfoModel(BehaviorInfo behaviorInfo) { + BehaviorInfoModel behaviorInfoModel = new BehaviorInfoModel(); + behaviorInfoModel.setName(behaviorInfo.getName()); + behaviorInfoModel.setParameters(new ArrayList()); + for (ParameterInfo param : behaviorInfo.getParameters()) { + ParameterInfoModel model = buildParameterInfoModel(param); + behaviorInfoModel.getParameters().add(model); + } + return behaviorInfoModel; + } + + private ParameterInfoModel buildParameterInfoModel(ParameterInfo param) { + ParameterInfoModel model = new ParameterInfoModel(); + model.setName(param.getName()); + model.setType(param.getType()); + return model; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/TestController.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/TestController.java new file mode 100644 index 00000000..736b1032 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/api/TestController.java @@ -0,0 +1,290 @@ +package org.bench4q.agent.api; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.log4j.Logger; +import org.bench4q.agent.datacollector.impl.BehaviorStatusCodeResult; +import org.bench4q.agent.parameterization.ParameterFileCollector; +import org.bench4q.agent.scenario.Scenario; +import org.bench4q.agent.scenario.ScenarioContext; +import org.bench4q.agent.scenario.ScenarioEngine; +import org.bench4q.agent.scenario.behavior.Behavior; +import org.bench4q.share.helper.MarshalHelper; +import org.bench4q.share.models.agent.BehaviorBriefModel; +import org.bench4q.share.models.agent.BehaviorStatusCodeResultModel; +import org.bench4q.share.models.agent.CleanTestResultModel; +import org.bench4q.share.models.agent.RunScenarioModel; +import org.bench4q.share.models.agent.RunScenarioResultModel; +import org.bench4q.share.models.agent.StopTestModel; +import org.bench4q.share.models.agent.TestBriefStatusModel; +import org.bench4q.share.models.agent.statistics.AgentBriefStatusModel; +import org.bench4q.share.models.agent.statistics.AgentBehaviorsBriefModel; +import org.bench4q.share.models.agent.statistics.AgentPageBriefModel; +import org.bench4q.share.models.agent.statistics.AgentPagesBriefModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.multipart.MultipartFile; + +@Controller +@RequestMapping("/test") +public class TestController { + private ScenarioEngine scenarioEngine; + private ParameterFileCollector paramFileCollector; + private Logger logger = Logger.getLogger(TestController.class); + + private Logger getLogger() { + return logger; + } + + private ScenarioEngine getScenarioEngine() { + return scenarioEngine; + } + + @Autowired + private void setScenarioEngine(ScenarioEngine scenarioEngine) { + this.scenarioEngine = scenarioEngine; + } + + private ParameterFileCollector getParamFileCollector() { + return paramFileCollector; + } + + @Autowired + private void setParamFileCollector(ParameterFileCollector paramFileCollector) { + this.paramFileCollector = paramFileCollector; + } + + @RequestMapping(value = "/submitScenarioWithParams", method = RequestMethod.POST) + @ResponseBody + public String submitParams( + @RequestParam("files[]") List files, + @RequestParam("scenarioModel") String scenarioModel) { + try { + UUID runId = UUID.randomUUID(); + this.getParamFileCollector().collectParamFiles(files, runId); + System.out.println(scenarioModel); + RunScenarioModel runScenarioModel = (RunScenarioModel) MarshalHelper + .unmarshal(RunScenarioModel.class, scenarioModel); + + this.getScenarioEngine().submitScenario(runId, + Scenario.scenarioBuilder(runScenarioModel), + runScenarioModel.getPoolSize()); + return MarshalHelper.tryMarshal(buildWith(runId)); + } catch (Exception e) { + logger.error("/submitScenarioWithParams", e); + return null; + } + } + + private RunScenarioResultModel buildWith(UUID runId) { + RunScenarioResultModel result = new RunScenarioResultModel(); + result.setRunId(runId); + return result; + } + + @RequestMapping(value = "/runWithParams/{runId}", method = RequestMethod.POST) + @ResponseBody + public RunScenarioResultModel runWithParams(@PathVariable UUID runId) { + return this.getScenarioEngine().runWith(runId) ? buildWith(runId) + : null; + } + + @RequestMapping(value = "/runWithoutParams", method = RequestMethod.POST) + @ResponseBody + public RunScenarioResultModel run( + @RequestBody RunScenarioModel runScenarioModel) + throws UnknownHostException { + Scenario scenario = Scenario.scenarioBuilder(runScenarioModel); + UUID runId = UUID.randomUUID(); + System.out.println(runScenarioModel.getPoolSize()); + this.getLogger().info(MarshalHelper.tryMarshal(runScenarioModel)); + if (runScenarioModel.getPoolSize() <= 0) { + logger.info("This RunScenarioModel's pool size is L.E zero, so throw out"); + return null; + } + this.getScenarioEngine().submitScenario(runId, scenario, + runScenarioModel.getPoolSize()); + + this.getScenarioEngine().runWith(runId); + RunScenarioResultModel runScenarioResultModel = new RunScenarioResultModel(); + runScenarioResultModel.setRunId(runId); + return runScenarioResultModel; + } + + @RequestMapping(value = "/briefAll/{runId}", method = RequestMethod.GET) + @ResponseBody + public TestBriefStatusModel briefAll(@PathVariable UUID runId) { + TestBriefStatusModel result = new TestBriefStatusModel(); + result.setScenarioBriefModel(this.brief(runId)); + result.setPagesBriefModel(this.pagesBrief(runId)); + result.setBehaviorsBriefModel(this.behaviorsBrief(runId)); + return result; + } + + @RequestMapping(value = "/brief/{runId}/{behaviorId}", method = RequestMethod.GET) + @ResponseBody + public BehaviorBriefModel behaviorBrief(@PathVariable UUID runId, + @PathVariable int behaviorId) { + ScenarioContext scenarioContext = this.getScenarioEngine() + .getRunningTests().get(runId); + if (scenarioContext == null) { + return null; + } + Map map = scenarioContext + .getDataStatistics().getBehaviorBriefStatistics(behaviorId); + return buildBehaviorBrief(runId, behaviorId, "", map); + } + + private BehaviorBriefModel buildBehaviorBrief(UUID runId, int behaviorId, + String behaviorUrl, Map map) { + List detailStatusCodeResultModels = new ArrayList(); + for (int statusCode : map.keySet()) { + BehaviorStatusCodeResultModel behaviorStatusCodeResultModel = new BehaviorStatusCodeResultModel(); + BehaviorStatusCodeResult detailStatusCodeResult = map + .get(statusCode); + behaviorStatusCodeResultModel.setStatusCode(statusCode); + behaviorStatusCodeResultModel + .setCount(detailStatusCodeResult.count); + behaviorStatusCodeResultModel + .setContentLength(detailStatusCodeResult.contentLength); + behaviorStatusCodeResultModel + .setMinResponseTime(detailStatusCodeResult.minResponseTime); + behaviorStatusCodeResultModel + .setMaxResponseTime(detailStatusCodeResult.maxResponseTime); + behaviorStatusCodeResultModel + .setContentType(detailStatusCodeResult.contentType); + behaviorStatusCodeResultModel + .setTotalResponseTimeThisTime(detailStatusCodeResult.totalResponseTimeThisTime); + detailStatusCodeResultModels.add(behaviorStatusCodeResultModel); + } + BehaviorBriefModel behaviorBriefModel = new BehaviorBriefModel(); + behaviorBriefModel.setBehaviorId(behaviorId); + behaviorBriefModel + .setDetailStatusCodeResultModels(detailStatusCodeResultModels); + behaviorBriefModel.setBehaviorUrl(behaviorUrl); + return behaviorBriefModel; + } + + @RequestMapping(value = "/pagesBrief/{runId}") + @ResponseBody + public AgentPagesBriefModel pagesBrief(@PathVariable UUID runId) { + ScenarioContext context = this.getScenarioEngine().getRunningTests() + .get(runId); + AgentPagesBriefModel result = new AgentPagesBriefModel(); + List pageBrieves = new ArrayList(); + + if (context == null || context.isFinished()) { + return null; + } + for (int i = 0; i < context.getScenario().getPages().length; i++) { + pageBrieves.add((AgentPageBriefModel) context.getDataStatistics() + .getPageBriefStatistics(i)); + } + result.setPageBriefModels(pageBrieves); + return result; + } + + @RequestMapping(value = "/pageBrief/{runId}/{pageId}") + @ResponseBody + public AgentPageBriefModel pageBrief(@PathVariable UUID runId, + @PathVariable int pageId) { + ScenarioContext context = this.getScenarioEngine().getRunningTests() + .get(runId); + if (context == null || context.isFinished()) { + return null; + } + return (AgentPageBriefModel) context.getDataStatistics() + .getPageBriefStatistics(pageId); + } + + @RequestMapping(value = "/behaviorsBrief/{runId}") + @ResponseBody + public AgentBehaviorsBriefModel behaviorsBrief(@PathVariable UUID runId) { + AgentBehaviorsBriefModel ret = new AgentBehaviorsBriefModel(); + List behaviorBriefModels = new ArrayList(); + ScenarioContext scenarioContext = this.getScenarioEngine() + .getRunningTests().get(runId); + if (scenarioContext == null || scenarioContext.isFinished()) { + return null; + } + for (Behavior behavior : scenarioContext.getScenario() + .getAllBehaviorsInScenario()) { + int behaviorId = behavior.getId(); + Map map = behavior + .getBehaviorBriefResult(scenarioContext.getDataStatistics()); + if (map == null) { + continue; + } + behaviorBriefModels.add(buildBehaviorBrief(runId, behaviorId, + behavior.getUrl(), map)); + } + ret.setBehaviorBriefModels(behaviorBriefModels); + return ret; + } + + @RequestMapping(value = "/brief/{runId}", method = RequestMethod.GET) + @ResponseBody + public AgentBriefStatusModel brief(@PathVariable UUID runId) { + ScenarioContext scenarioContext = this.getScenarioEngine() + .getRunningTests().get(runId); + if (scenarioContext == null) { + return null; + } + AgentBriefStatusModel agentStatusModel = (AgentBriefStatusModel) scenarioContext + .getDataStatistics().getScenarioBriefStatistics(); + agentStatusModel.setvUserCount(scenarioContext.getExecutor() + .getActiveCount()); + return agentStatusModel; + } + + @RequestMapping(value = "/stop/{runId}", method = { RequestMethod.GET, + RequestMethod.POST }) + @ResponseBody + public StopTestModel stop(@PathVariable UUID runId) { + System.out.println("stop method"); + ScenarioContext scenarioContext = this.getScenarioEngine() + .getRunningTests().get(runId); + if (scenarioContext == null) { + return null; + } + scenarioContext.setEndDate(new Date(System.currentTimeMillis())); + System.out.println("when before stop, classId:" + + scenarioContext.getExecutor().toString()); + scenarioContext.getExecutor().shutdown(); + scenarioContext.getExecutor().shutdownNow(); + System.out.println("when after stop, classId:" + + scenarioContext.getExecutor().toString()); + scenarioContext.setFinished(true); + StopTestModel stopTestModel = new StopTestModel(); + stopTestModel.setSuccess(true); + clean(runId); + return stopTestModel; + } + + @RequestMapping(value = "/clean/{runId}", method = RequestMethod.GET) + @ResponseBody + public CleanTestResultModel clean(@PathVariable UUID runId) { + ScenarioContext scenarioContext = this.getScenarioEngine() + .getRunningTests().get(runId); + if (scenarioContext == null) { + return null; + } + scenarioContext.getExecutor().shutdownNow(); + this.getScenarioEngine().getRunningTests().remove(runId); + System.gc(); + CleanTestResultModel cleanTestResultModel = new CleanTestResultModel(); + cleanTestResultModel.setSuccess(true); + return cleanTestResultModel; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/DataCollector.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/DataCollector.java new file mode 100644 index 00000000..94c13c9f --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/DataCollector.java @@ -0,0 +1,20 @@ +package org.bench4q.agent.datacollector; + +import java.util.Map; + +import org.bench4q.agent.datacollector.impl.BehaviorStatusCodeResult; +import org.bench4q.agent.scenario.BehaviorResult; +import org.bench4q.agent.scenario.PageResult; + +public interface DataCollector { + public void add(BehaviorResult behaviorResult); + + public void add(PageResult pageResult); + + public Object getScenarioBriefStatistics(); + + public Map getBehaviorBriefStatistics( + int behaviorId); + + public Object getPageBriefStatistics(int pageId); +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/AbstractDataCollector.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/AbstractDataCollector.java new file mode 100644 index 00000000..e14a0b75 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/AbstractDataCollector.java @@ -0,0 +1,82 @@ +package org.bench4q.agent.datacollector.impl; + +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.bench4q.agent.Main; +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.helper.ApplicationContextHelper; +import org.bench4q.agent.scenario.BehaviorResult; +import org.bench4q.agent.storage.StorageHelper; +import org.bench4q.share.models.agent.BehaviorResultModel; + +public abstract class AbstractDataCollector implements DataCollector { + protected StorageHelper storageHelper; + + protected StorageHelper getStorageHelper() { + return storageHelper; + } + + public void setStorageHelper(StorageHelper storageHelper) { + this.storageHelper = storageHelper; + } + + public AbstractDataCollector() { + mustDoWhenIniti(); + } + + // Each sub class should call this in their constructor + protected void mustDoWhenIniti() { + this.setStorageHelper(ApplicationContextHelper.getContext().getBean( + StorageHelper.class)); + } + + public void add(final BehaviorResult behaviorResult) { + if (!Main.IS_TO_SAVE_DETAIL) { + return; + } + if (behaviorResult == null) { + return; + } + Runnable runnable = new Runnable() { + public void run() { + storageHelper.getLocalStorage().writeFile( + buildBehaviorResultModel(behaviorResult) + .getModelString(), + calculateSavePath(behaviorResult)); + } + }; + ExecutorService executorService = Executors + .newSingleThreadScheduledExecutor(); + executorService.execute(runnable); + executorService.shutdown(); + } + + private BehaviorResultModel buildBehaviorResultModel( + BehaviorResult behaviorResult) { + BehaviorResultModel resultModel = new BehaviorResultModel(); + resultModel.setBehaviorId(behaviorResult.getBehaviorId()); + resultModel.setBehaviorName(behaviorResult.getBehaviorName()); + resultModel.setContentLength(behaviorResult.getContentLength()); + resultModel.setContentType(behaviorResult.getContentType()); + resultModel.setEndDate(behaviorResult.getEndDate()); + resultModel.setPluginId(behaviorResult.getPluginId()); + resultModel.setPluginName(behaviorResult.getPluginName()); + resultModel.setResponseTime(behaviorResult.getResponseTime()); + resultModel.setShouldBeCountResponseTime(behaviorResult + .isShouldBeCountResponseTime()); + resultModel.setStartDate(behaviorResult.getStartDate()); + resultModel.setStatusCode(behaviorResult.getStatusCode()); + resultModel.setSuccess(behaviorResult.isSuccess()); + return resultModel; + } + + protected abstract String calculateSavePath(BehaviorResult behaviorResult); + + public abstract Object getScenarioBriefStatistics(); + + public abstract Map getBehaviorBriefStatistics( + int id); + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/BehaviorResultCollector.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/BehaviorResultCollector.java new file mode 100644 index 00000000..09cd8dab --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/BehaviorResultCollector.java @@ -0,0 +1,5 @@ +package org.bench4q.agent.datacollector.impl; + +public class BehaviorResultCollector { + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/BehaviorStatusCodeResult.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/BehaviorStatusCodeResult.java new file mode 100644 index 00000000..5fe233de --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/BehaviorStatusCodeResult.java @@ -0,0 +1,52 @@ +package org.bench4q.agent.datacollector.impl; + +import java.lang.reflect.Field; + +public class BehaviorStatusCodeResult { + public long count; + public long contentLength; + public long minResponseTime; + public long maxResponseTime; + public long totalResponseTimeThisTime; + public String contentType; + + public BehaviorStatusCodeResult(String contentType) { + this.totalResponseTimeThisTime = 0; + this.contentType = contentType; + this.count = 0; + this.contentLength = 0; + this.minResponseTime = Long.MAX_VALUE; + this.maxResponseTime = Long.MIN_VALUE; + } + + public static boolean isSuccess(int statusCode) { + return statusCode == 200; + } + + public boolean equals(Object expectedObj) { + Field[] fields = this.getClass().getDeclaredFields(); + boolean equal = true; + try { + for (Field field : fields) { + field.setAccessible(true); + if (field.getName().equals("contentType")) { + field.get(expectedObj).equals(field.get(this)); + continue; + } + if (field.getLong(this) != field.getLong(expectedObj)) { + System.out.println(field.getName() + + " is diferent, this is " + field.getLong(this) + + ", and the expected is " + + field.getLong(expectedObj)); + equal = false; + } + + } + } catch (Exception e) { + e.printStackTrace(); + equal = false; + + } + return equal; + } +} \ No newline at end of file diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/PageResultCollector.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/PageResultCollector.java new file mode 100644 index 00000000..f046c746 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/PageResultCollector.java @@ -0,0 +1,110 @@ +package org.bench4q.agent.datacollector.impl; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.bench4q.agent.scenario.BehaviorResult; +import org.bench4q.agent.scenario.PageResult; +import org.bench4q.share.models.agent.statistics.AgentPageBriefModel; + +public class PageResultCollector extends AbstractDataCollector { + Map pageBriefMap; + + private Map getPageBriefMap() { + return pageBriefMap; + } + + private void setPageBriefMap(Map pageBriefMap) { + this.pageBriefMap = pageBriefMap; + } + + public PageResultCollector() { + this.setPageBriefMap(new HashMap()); + } + + public void add(PageResult pageResult) { + if (pageResult == null || pageResult.getPageId() < 0) { + return; + } + PageBrief pageBrief = guardTheValueOfThePageIdExists(pageResult + .getPageId()); + pageBrief.countThisTime++; + pageBrief.countFromBegin++; + pageBrief.totalResponseTimeThisTime += pageResult.getExecuteRange(); + pageBrief.latesTimeResponseTime = pageResult.getExecuteRange(); + if (pageResult.getExecuteRange() > pageBrief.maxResponseTimeFromBegin) { + pageBrief.maxResponseTimeFromBegin = pageResult.getExecuteRange(); + } + if (pageResult.getExecuteRange() < pageBrief.minResponseTimeFromBegin) { + pageBrief.minResponseTimeFromBegin = pageResult.getExecuteRange(); + } + } + + private synchronized PageBrief guardTheValueOfThePageIdExists(int pageId) { + if (!this.getPageBriefMap().containsKey(pageId)) { + this.getPageBriefMap().put(pageId, new PageBrief()); + } + return this.getPageBriefMap().get(pageId); + } + + public Object getPageBriefStatistics(int pageId) { + PageBrief pageBrief = guardTheValueOfThePageIdExists(pageId); + AgentPageBriefModel result = new AgentPageBriefModel(); + result.setCountFromBegin(pageBrief.countFromBegin); + result.setCountThisTime(pageBrief.countThisTime); + result.setMaxResponseTimeFromBegin(pageBrief.maxResponseTimeFromBegin); + result.setMinResponseTimeFromBegin(pageBrief.minResponseTimeFromBegin); + result.setTotalResponseTimeThisTime(pageBrief.totalResponseTimeThisTime); + result.setPageId(pageId); + long nowTime = new Date().getTime(); + result.setTimeFrame(nowTime - pageBrief.lastSampleTime); + result.setLatestResponseTime(pageBrief.latesTimeResponseTime); + pageBrief.resetTemperatyField(); + return result; + } + + @Override + public void add(BehaviorResult behaviorResult) { + } + + @Override + protected String calculateSavePath(BehaviorResult behaviorResult) { + return null; + } + + @Override + public Object getScenarioBriefStatistics() { + return null; + } + + @Override + public Map getBehaviorBriefStatistics( + int id) { + return null; + } + + public class PageBrief { + public long lastSampleTime; + public long countThisTime; + public long totalResponseTimeThisTime; + public long maxResponseTimeFromBegin; + public long minResponseTimeFromBegin; + public long countFromBegin; + public long latesTimeResponseTime; + + public PageBrief() { + resetTemperatyField(); + this.maxResponseTimeFromBegin = Long.MIN_VALUE; + this.minResponseTimeFromBegin = Long.MAX_VALUE; + this.countFromBegin = 0; + this.latesTimeResponseTime = 0; + } + + public void resetTemperatyField() { + this.lastSampleTime = new Date().getTime(); + this.countThisTime = 0; + this.totalResponseTimeThisTime = 0; + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/ScenarioResultCollector.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/ScenarioResultCollector.java new file mode 100644 index 00000000..557282d1 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/datacollector/impl/ScenarioResultCollector.java @@ -0,0 +1,278 @@ +package org.bench4q.agent.datacollector.impl; + +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.bench4q.agent.scenario.BehaviorResult; +import org.bench4q.agent.scenario.PageResult; +import org.bench4q.share.models.agent.statistics.AgentBriefStatusModel; + +/** + * This class collect the behavior result and statistic it. + * + * @author coderfengyun + * + */ +public class ScenarioResultCollector extends AbstractDataCollector { + private long timeOfPreviousCall; + private long failCountOfThisCall; + private long successCountOfThisCall; + private long totalResponseTimeOfThisCall; + private long maxResponseTimeOfThisCall; + private long minResponseTimeOfThisCall; + private long totalSqureResponseTimeOfThisCall; + private long cumulativeSucessfulCount; + private long cumulativeFailCount; + private static long TIME_UNIT = 1000; + private UUID testID; + private PageResultCollector pageResultCollector; + // The first integer is the behavior's id, and the second integer is + // the StatusCode of this behaviorResult. + private Map> detailMap; + + private void setTimeOfPreviousCall(long timeOfPreviousCall) { + this.timeOfPreviousCall = timeOfPreviousCall; + } + + private void setFailCountOfThisCall(long failCountOfThisCall) { + this.failCountOfThisCall = failCountOfThisCall; + } + + private long getSuccessCountOfThisCall() { + return successCountOfThisCall; + } + + private void setSuccessCountOfThisCall(long successCountOfThisCall) { + this.successCountOfThisCall = successCountOfThisCall; + } + + private void setTotalResponseTimeOfThisCall(long totalResponseTimeOfThisCall) { + this.totalResponseTimeOfThisCall = totalResponseTimeOfThisCall; + } + + private long getMaxResponseTimeOfThisCall() { + return maxResponseTimeOfThisCall; + } + + private void setMaxResponseTimeOfThisCall(long maxResponseTimeOfThisCall) { + this.maxResponseTimeOfThisCall = maxResponseTimeOfThisCall; + } + + private long getMinResponseTimeOfThisCall() { + return minResponseTimeOfThisCall; + } + + private void setMinResponseTimeOfThisCall(long minResponseTimeOfThisCall) { + this.minResponseTimeOfThisCall = minResponseTimeOfThisCall; + } + + private void setTotalSqureResponseTimeOfThisCall( + long totalSqureResponseTimeOfThisCall) { + this.totalSqureResponseTimeOfThisCall = totalSqureResponseTimeOfThisCall; + } + + private void setCumulativeSucessfulCount(long cumulativeSucessfulCount) { + this.cumulativeSucessfulCount = cumulativeSucessfulCount; + } + + private void setCumulativeFailCount(long cumulativeFailCount) { + this.cumulativeFailCount = cumulativeFailCount; + } + + private String getTestID() { + return testID == null ? "default" : testID.toString(); + } + + private void setTestID(UUID testID) { + this.testID = testID; + } + + private void setDetailMap( + Map> detailMap) { + this.detailMap = detailMap; + } + + private PageResultCollector getPageResultCollector() { + return pageResultCollector; + } + + private void setPageResultCollector(PageResultCollector pageResultCollector) { + this.pageResultCollector = pageResultCollector; + } + + public ScenarioResultCollector(UUID testId) { + this.setTestID(testId); + this.setPageResultCollector(new PageResultCollector()); + init(); + } + + private void init() { + reset(); + this.setCumulativeFailCount(0); + this.setCumulativeSucessfulCount(0); + this.setDetailMap(new HashMap>()); + } + + private void reset() { + this.setTimeOfPreviousCall(System.currentTimeMillis()); + this.setFailCountOfThisCall(0); + this.setMaxResponseTimeOfThisCall(Long.MIN_VALUE); + this.setMinResponseTimeOfThisCall(Long.MAX_VALUE); + this.setSuccessCountOfThisCall(0); + this.setTotalResponseTimeOfThisCall(0); + this.setTotalSqureResponseTimeOfThisCall(0); + } + + // /////////////////////////////// + // DataStatistics Interface start + // /////////////////////////////// + + public AgentBriefStatusModel getScenarioBriefStatistics() { + AgentBriefStatusModel result = new AgentBriefStatusModel(); + result.setTimeFrame(System.currentTimeMillis() + - this.timeOfPreviousCall); + if (this.getSuccessCountOfThisCall() == 0) { + result.setMaxResponseTime(0); + result.setMinResponseTime(0); + } else { + result.setMinResponseTime(this.minResponseTimeOfThisCall); + result.setMaxResponseTime(this.maxResponseTimeOfThisCall); + } + this.cumulativeSucessfulCount += this.successCountOfThisCall; + result.setSuccessCountFromBegin(this.cumulativeSucessfulCount); + this.cumulativeFailCount += this.failCountOfThisCall; + result.setFailCountFromBegin(this.cumulativeFailCount); + if (result.getTimeFrame() == 0) { + result.setSuccessThroughputThisTime(0); + result.setFailThroughputThisTime(0); + } else { + result.setSuccessThroughputThisTime(this.successCountOfThisCall + * TIME_UNIT / result.getTimeFrame()); + result.setFailThroughputThisTime(this.failCountOfThisCall + * TIME_UNIT / result.getTimeFrame()); + } + result.setTotalResponseTimeThisTime(this.totalResponseTimeOfThisCall); + result.setSuccessCountThisTime(this.successCountOfThisCall); + result.setFailCountThisTime(this.failCountOfThisCall); + result.setTotalSqureResponseTimeThisTime(this.totalSqureResponseTimeOfThisCall); + reset(); + return result; + } + + // /////////////////////////////// + // DataStatistics Interface end + // /////////////////////////////// + /** + * For the failed one, only the fail count statistics will be added, Others + * of this failed one will be ignored. + * + * @param behaviorResult + */ + + private void statisticScenarioBriefResult(BehaviorResult behaviorResult) { + if (behaviorResult.isSuccess()) { + this.successCountOfThisCall++; + this.totalResponseTimeOfThisCall += behaviorResult + .getResponseTime(); + this.totalSqureResponseTimeOfThisCall += ((long) behaviorResult + .getResponseTime()) * behaviorResult.getResponseTime(); + if (behaviorResult.getResponseTime() > this + .getMaxResponseTimeOfThisCall()) { + this.setMaxResponseTimeOfThisCall(behaviorResult + .getResponseTime()); + } + if (behaviorResult.getResponseTime() < this + .getMinResponseTimeOfThisCall()) { + this.setMinResponseTimeOfThisCall(behaviorResult + .getResponseTime()); + } + } else { + this.failCountOfThisCall++; + } + } + + private void statisticBehaviorBriefResult(BehaviorResult behaviorResult) { + insertWhenNotExist(behaviorResult); + Map detailStatusMap = this.detailMap + .get(behaviorResult.getBehaviorId()); + // TODO: there's a problem about concurrency + guardStatusMapExists(behaviorResult, detailStatusMap); + BehaviorStatusCodeResult statusCodeResult = detailStatusMap + .get(behaviorResult.getStatusCode()); + statusCodeResult.count++; + if (!behaviorResult.isSuccess()) { + statusCodeResult.maxResponseTime = 0; + statusCodeResult.minResponseTime = 0; + statusCodeResult.contentLength = 0; + statusCodeResult.totalResponseTimeThisTime = 0; + return; + } + statusCodeResult.contentLength += behaviorResult.getContentLength(); + statusCodeResult.totalResponseTimeThisTime += behaviorResult + .getResponseTime(); + if (behaviorResult.getResponseTime() > statusCodeResult.maxResponseTime) { + statusCodeResult.maxResponseTime = behaviorResult.getResponseTime(); + } + if (behaviorResult.getResponseTime() < statusCodeResult.minResponseTime) { + statusCodeResult.minResponseTime = behaviorResult.getResponseTime(); + } + } + + private synchronized void guardStatusMapExists( + BehaviorResult behaviorResult, + Map detailStatusMap) { + if (!detailStatusMap.containsKey(behaviorResult.getStatusCode())) { + detailStatusMap.put( + new Integer(behaviorResult.getStatusCode()), + new BehaviorStatusCodeResult(behaviorResult + .getContentType())); + } + } + + private synchronized void insertWhenNotExist(BehaviorResult behaviorResult) { + if (!this.detailMap.containsKey(behaviorResult.getBehaviorId())) { + this.detailMap.put(new Integer(behaviorResult.getBehaviorId()), + new HashMap()); + } + } + + @Override + protected String calculateSavePath(BehaviorResult behaviorResult) { + Date now = new Date(); + + return "DetailResults" + System.getProperty("file.separator") + + new SimpleDateFormat("yyyyMMdd").format(now) + + System.getProperty("file.separator") + this.getTestID() + "_" + + behaviorResult.getBehaviorId() + "_" + + new SimpleDateFormat("hhmm") + ".txt"; + } + + public void add(PageResult pageResult) { + this.getPageResultCollector().add(pageResult); + } + + @Override + public void add(BehaviorResult behaviorResult) { + super.add(behaviorResult); + statisticScenarioBriefResult(behaviorResult); + statisticBehaviorBriefResult(behaviorResult); + } + + @Override + public Map getBehaviorBriefStatistics( + int behaviorId) { + if (!this.detailMap.containsKey(behaviorId)) { + return null; + } + return Collections.unmodifiableMap(this.detailMap.get(behaviorId)); + } + + public Object getPageBriefStatistics(int pageId) { + return this.getPageResultCollector().getPageBriefStatistics(pageId); + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/helper/ApplicationContextHelper.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/helper/ApplicationContextHelper.java new file mode 100644 index 00000000..4ace1b14 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/helper/ApplicationContextHelper.java @@ -0,0 +1,26 @@ +package org.bench4q.agent.helper; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class ApplicationContextHelper implements ApplicationContextAware { + + private static ApplicationContext context; + + public static ApplicationContext getContext() { + return context; + } + + private void setContext(ApplicationContext context) { + ApplicationContextHelper.context = context; + } + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.setContext(applicationContext); + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/ParameterFileCollector.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/ParameterFileCollector.java new file mode 100644 index 00000000..54bdb87a --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/ParameterFileCollector.java @@ -0,0 +1,33 @@ +package org.bench4q.agent.parameterization; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.UUID; + +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Component +public class ParameterFileCollector { + private static final String FILE_SEPARATOR = System + .getProperty("file.separator"); + + public void collectParamFiles(List files, UUID runId) + throws IOException { + for (MultipartFile file : files) { + file.transferTo(new File(guardDirExists(runId) + + file.getOriginalFilename())); + } + } + + private String guardDirExists(UUID runId) { + String dirPath = "ScenarioParameters" + FILE_SEPARATOR + + runId.toString() + FILE_SEPARATOR; + File dirFile = new File(dirPath); + if (!dirFile.exists()) { + dirFile.mkdirs(); + } + return dirPath; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/SessionObject.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/SessionObject.java new file mode 100644 index 00000000..a96586f4 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/SessionObject.java @@ -0,0 +1,14 @@ +package org.bench4q.agent.parameterization; + +import java.util.Map; + +public interface SessionObject { + + public String getParam(String name); + + public void saveRuntimeParam(String name, String value); + + public void doCleanUp(); + + public void saveRuntimeParams(Map runTimeParams); +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/InstanceControler.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/InstanceControler.java new file mode 100644 index 00000000..e14e9164 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/InstanceControler.java @@ -0,0 +1,183 @@ +package org.bench4q.agent.parameterization.impl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.bench4q.agent.parameterization.SessionObject; + +public class InstanceControler implements SessionObject { + private String userDefineParameterFolderPath = "/home/yxsh/git/Bench4Q-Agent/parameterClass/"; + private UUID instandid = java.util.UUID.randomUUID(); + private Set usedClassName = new HashSet(); + private Map objMap = new HashMap(); + private Map runtimeParaMap = new HashMap(); + private Map cacheObjMap = new HashMap(); + private ReentrantReadWriteLock mapRWLock = new ReentrantReadWriteLock(); + + String instanceLevelGetParameter(String name, String className, + String functionName, Object[] args) { + + boolean hasThisClass = false; + mapRWLock.readLock().lock(); + hasThisClass = objMap.containsKey(className); + mapRWLock.readLock().unlock(); + if (false == hasThisClass) { + createObj(className); + } + Object instance = getObj(className); + Object result = null; + try { + Class[] argTypeArr = new Class[args.length + 2]; + argTypeArr[0] = instandid.getClass(); + argTypeArr[1] = this.cacheObjMap.getClass(); + Object[] totalArgs = new Object[args.length + 2]; + totalArgs[0] = instandid; + totalArgs[1] = this.cacheObjMap; + for (int i = 2; i < args.length + 2; i++) { + argTypeArr[i] = args[i - 2].getClass(); + totalArgs[i] = args[i - 2]; + } + Method m = instance.getClass().getMethod(functionName, argTypeArr); + result = m.invoke(instance, totalArgs); + } catch (Exception ex) { + System.out.println(ex.getMessage() + ex.getStackTrace()); + System.out.println(((InvocationTargetException) ex) + .getTargetException().getMessage()); + return null; + } + runtimeParaMap.put(name, (String) result); + return (String) result; + + } + + String getParameterByContext(String name) { + if (false == this.runtimeParaMap.containsKey(name)) { + return null; + } + return runtimeParaMap.get(name); + } + + private boolean createObj(String className) { + try { + MyFileClassLoader cl = new MyFileClassLoader(); + cl.setClassPath(userDefineParameterFolderPath); + Class cls = cl.loadClass(className); + Object instance = cls.newInstance(); + mapRWLock.writeLock().lock(); + objMap.put(className, instance); + + } catch (Exception ex) { + return false; + } + mapRWLock.writeLock().unlock(); + return true; + } + + private Object getObj(String className) { + Object result = null; + mapRWLock.readLock().lock(); + objMap.get(className); + mapRWLock.readLock().unlock(); + return result; + } + + String getParameter(String name, String className, String functionName, + Object[] args) { + + ParametersFactory pf = ParametersFactory.getInstance(); + boolean hasThisClass = pf.containObj(className); + if (false == hasThisClass) { + pf.createObj(className); + } + + Object instance = pf.getObj(className); + Object result = null; + try { + Class[] argTypeArr = new Class[args.length + 2]; + argTypeArr[0] = instandid.getClass(); + argTypeArr[1] = this.cacheObjMap.getClass(); + Object[] totalArgs = new Object[args.length + 2]; + totalArgs[0] = instandid; + totalArgs[1] = this.cacheObjMap; + for (int i = 2; i < args.length + 2; i++) { + argTypeArr[i] = args[i - 2].getClass(); + totalArgs[i] = args[i - 2]; + } + + Method m = instance.getClass().getMethod(functionName, argTypeArr); + + result = m.invoke(instance, totalArgs); + + } catch (Exception ex) { + System.out.println(ex.getMessage() + ex.getStackTrace()); + System.out.println(((InvocationTargetException) ex) + .getTargetException().getMessage()); + return null; + } + + usedClassName.add(className); + runtimeParaMap.put(name, (String) result); + return (String) result; + } + + /** + * Implement SessionObject begin + */ + + public String getParam(String name) { + if (!(name.startsWith(""))) + return name; + return ParameterizationParser.parse(name, this); + } + + public void saveRuntimeParam(String name, String value) { + runtimeParaMap.put(name, value); + } + + public void saveRuntimeParams(Map runTimeParams) { + runtimeParaMap.putAll(runTimeParams); + } + + public void doCleanUp() { + this.releaseAll(); + } + + /** + * Implement SessionObject end + */ + + private void releaseAll() { + for (String xx : usedClassName) { + release(xx); + } + } + + private void release(String className) { + ParametersFactory pf = ParametersFactory.getInstance(); + boolean hasThisClass = pf.containObj(className); + if (false == hasThisClass) { + pf.createObj(className); + } + + Object instance = pf.getObj(className); + + try { + + Method m = instance.getClass().getMethod("unreg", + instandid.getClass()); + + m.invoke(instance, instandid); + + } catch (Exception ex) { + System.out.println("realse failed"); + } + + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/MyFileClassLoader.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/MyFileClassLoader.java new file mode 100644 index 00000000..44448d68 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/MyFileClassLoader.java @@ -0,0 +1,98 @@ +package org.bench4q.agent.parameterization.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class MyFileClassLoader extends ClassLoader { + + private String classPath; + + public static void main(String[] args) throws ClassNotFoundException, + InstantiationException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException { + MyFileClassLoader fileClsLoader = new MyFileClassLoader(); + fileClsLoader + .setClassPath("E:\\j2ee_proj\\skythink\\WebContent\\WEB-INF\\classes\\"); + Class cls = fileClsLoader + .loadClass("com.cmw.entity.sys.AccordionEntity"); + Object obj = cls.newInstance(); + Method[] mthds = cls.getMethods(); + for (Method mthd : mthds) { + String methodName = mthd.getName(); + System.out.println("mthd.name=" + methodName); + } + System.out.println("obj.class=" + obj.getClass().getName()); + System.out.println("obj.class=" + cls.getClassLoader().toString()); + System.out.println("obj.class=" + + cls.getClassLoader().getParent().toString()); + } + + /** + * ��������ַ��ָ����Ŀ¼�����࣬����������� + */ + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] classData = null; + try { + classData = loadClassData(name); + } catch (IOException e) { + e.printStackTrace(); + } + return super.defineClass(name, classData, 0, classData.length); + } + + /** + * ��������ַ������ byte ����� + * + * @param name + * �����ַ� ���磺 com.cmw.entity.SysEntity + * @return �������ļ� byte ����� + * @throws IOException + */ + private byte[] loadClassData(String name) throws IOException { + File file = getFile(name); + @SuppressWarnings("resource") + FileInputStream fis = new FileInputStream(file); + byte[] arrData = new byte[(int) file.length()]; + fis.read(arrData); + return arrData; + } + + /** + * ��������ַ���һ�� File ���� + * + * @param name + * �����ַ� + * @return File ���� + * @throws FileNotFoundException + */ + private File getFile(String name) throws FileNotFoundException { + File dir = new File(classPath); + if (!dir.exists()) + throw new FileNotFoundException(classPath + " Ŀ¼�����ڣ�"); + String _classPath = classPath.replaceAll("[\\\\]", "/"); + int offset = _classPath.lastIndexOf("/"); + name = name.replaceAll("[.]", "/"); + if (offset != -1 && offset < _classPath.length() - 1) { + _classPath += "/"; + } + _classPath += name + ".class"; + dir = new File(_classPath); + if (!dir.exists()) + throw new FileNotFoundException(dir + " �����ڣ�"); + return dir; + } + + public String getClassPath() { + return classPath; + } + + public void setClassPath(String classPath) { + this.classPath = classPath; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_File.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_File.java new file mode 100644 index 00000000..aaca0b6d --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_File.java @@ -0,0 +1,18 @@ +package org.bench4q.agent.parameterization.impl; + +import java.io.BufferedReader; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class Para_File { + + @SuppressWarnings("unused") + private Map readBuffer = new HashMap(); + + public void getFromFile(UUID id, String fileName, String column, + String firstData, String byNumber) { + + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_GetEletronicCombine.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_GetEletronicCombine.java new file mode 100644 index 00000000..16295ae5 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_GetEletronicCombine.java @@ -0,0 +1,32 @@ +package org.bench4q.agent.parameterization.impl; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class Para_GetEletronicCombine { + + public class eletronicParas + { + String beginUser; + String endUser; + String beginTime; + String endTime; + } + public Map useInstanceMap = new HashMap(); + @SuppressWarnings("deprecation") + Date currentTimeLoop = new Date("2014-01-01"); + long currentUser = 10001; + ReentrantReadWriteLock timeRWLock = new ReentrantReadWriteLock(); + + public Para_GetEletronicCombine() { + + } + + public String getBeginUser(UUID id) { + return null; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_IteratorNumber.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_IteratorNumber.java new file mode 100644 index 00000000..e4d42743 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_IteratorNumber.java @@ -0,0 +1,29 @@ +package org.bench4q.agent.parameterization.impl; + +import java.util.Map; +import java.util.UUID; + +public class Para_IteratorNumber { + public Long iteratorNum = new Long(0); + + /** + * For all methods, they will has these two params + * + * @param id + * @param a + * @return + */ + public String getIteratorNumber(UUID id, Map a) { + long result = 0; + synchronized (iteratorNum) { + iteratorNum++; + result = iteratorNum; + } + String ret = String.valueOf(result); + return ret; + } + + public void unreg(UUID id) { + + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_RandomNumber.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_RandomNumber.java new file mode 100644 index 00000000..f0b6f360 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_RandomNumber.java @@ -0,0 +1,28 @@ +package org.bench4q.agent.parameterization.impl; + +import java.util.Random; +import java.util.UUID; + +public class Para_RandomNumber { + + public String getRandomIntegerNumber(UUID id,String begin, String end, String stringformat) + { + + Random r = new Random(); + int beginNum = Integer.parseInt(begin); + int endNum = Integer.parseInt(end); + + int result = r.nextInt(endNum-beginNum) +beginNum; + return String.format(stringformat,result); + } + + public String getRandomDouble(UUID id , String begin, String end , String stringformat) + { + Random r = new Random(); + double beginNum = Integer.parseInt(begin); + double endNum = Integer.parseInt(end); + + double result = r.nextDouble()*(endNum-beginNum) +beginNum; + return String.format(stringformat, result); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_Table.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_Table.java new file mode 100644 index 00000000..201003a5 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_Table.java @@ -0,0 +1,271 @@ +package org.bench4q.agent.parameterization.impl; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentHashMap; + +public class Para_Table { + public final int cacheCap = 5000;// 1 sequence 2 random + public final int cacheSize = 1000;// 1 sequence 2 random + public final int readCharSize = 10000; + public ConcurrentHashMap readerMap = new ConcurrentHashMap(); + + public abstract class Reader { + public final Table t; + + public Reader(Table table) { + this.t = table; + } + + public abstract TableRow nextRow(); + + } + + public class RandomReader extends Reader { + public ArrayBlockingQueue queue; + + public RandomReader(ArrayBlockingQueue queue, Table t) { + super(t); + this.queue = queue; + } + + @Override + public TableRow nextRow() { + TableRow result = null; + do { + if (queue.size() == 0) { + synchronized (queue) { + if (queue.size() == 0) { + List rows = t.readRows(); + int n = rows.size(); + Random r = new Random(); + for (int i = 0; i < n; i++) { + int next = r.nextInt(n); + TableRow tempRow = rows.get(i); + rows.set(i, rows.get(next)); + rows.set(next, tempRow); + } + queue.addAll(rows); + } + } + } + result = queue.poll(); + } while (result == null); + return result; + } + + } + + public class SequenceReader extends Reader { + public ArrayBlockingQueue queue; + + public SequenceReader(ArrayBlockingQueue queue, Table t) { + super(t); + this.queue = queue; + } + + @Override + public TableRow nextRow() { + TableRow result = null; + do { + if (queue.size() == 0) { + synchronized (queue) { + if (queue.size() == 0) { + List rows = t.readRows(); + queue.addAll(rows); + } + } + } + result = queue.poll(); + } while (result == null); + return result; + } + + } + + public abstract class Table { + String sourceValue; + int firstRow; + + public Table(String sourceValue, int firstRow) { + this.sourceValue = sourceValue; + } + + public abstract List readRows(); + + public List rows = new ArrayList(); + + public int getTime = 0; + + public boolean add(TableRow r) { + return rows.add(r); + } + } + + public class FileTable extends Table { + private BufferedReader bfr; + char splitChar; + char lineChar; + + public FileTable(String sourceValue, int firstRow, char splitChar, + char lineChar) { + super(sourceValue, firstRow); + this.splitChar = splitChar; + this.lineChar = lineChar; + try { + createBFR(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private void createBFR() throws IOException { + FileInputStream fis = new FileInputStream(sourceValue); + InputStreamReader ir = new InputStreamReader(fis); + bfr = new BufferedReader(ir); + for (int i = 0; i < firstRow;) { + char readChar = (char) bfr.read(); + if (readChar == lineChar) + i++; + } + + } + + @Override + public List readRows() { + StringBuilder target = new StringBuilder(); + List result = new ArrayList(); + TableRow tempTableRow = new TableRow(); + try { + for (int i = 0; i < cacheSize;) { + int tt = bfr.read(); + char readBuff = (char) tt; + if (tt == -1) { + createBFR(); + break; + } else if (readBuff == this.splitChar) { + String cellString = target.toString(); + tempTableRow.AddCell(cellString); + target = new StringBuilder(); + continue; + } else if (readBuff == this.lineChar) { + tempTableRow.AddCell(target.toString()); + result.add(tempTableRow); + tempTableRow = new TableRow(); + target = new StringBuilder(); + i++; + continue; + } + target.append(readBuff); + } + } catch (IOException ioex) { + return result; + } + if (target.length() > 0) { + tempTableRow.AddCell(target.toString()); + result.add(tempTableRow); + target = new StringBuilder(); + } + return result; + } + + } + + public class StringTable extends Table { + + char splitChar; + char lineChar; + + public StringTable(String sourceValue, int firstRow, char splitChar, + char lineChar) { + super(sourceValue, firstRow); + this.splitChar = splitChar; + this.lineChar = lineChar; + } + + @Override + public List readRows() { + String readStr = this.sourceValue; + String[] tokens = readStr.split(String.valueOf(lineChar)); + List result = new ArrayList(); + for (String line : tokens) { + TableRow tempRow = new TableRow(); + String[] columns = line.split(String.valueOf(splitChar)); + for (String column : columns) { + tempRow.AddCell(column); + } + result.add(tempRow); + } + return result; + } + + } + + public class TableRow { + public List cells = new ArrayList(); + + public void AddCell(String s) { + cells.add(s); + } + } + + // org.bench4q.agent.parameterization.impl.Para_Table.getTableColumnValue(java.util.UUID, + // java.util.HashMap, java.lang.String, java.lang.String, java.lang.String, + // java.lang.String, java.lang.String, java.lang.String, java.lang.String) + + public String getTableColumnValue(UUID id, + HashMap objCache, String source, + String sourceValue, String firstRow, String nextRow, + String splitChar, String lineChar, String column) { + int fRow = Integer.parseInt(firstRow); + char sChar = splitChar.charAt(0); + char lChar = lineChar.charAt(0); + int col = Integer.parseInt(column); + TableRow resultRow = null; + Table table = null; + Reader reader = null; + if (objCache.containsKey(sourceValue) == true) { + resultRow = (TableRow) objCache.get(sourceValue); + return resultRow.cells.get(col); + } + + if (this.readerMap.containsKey(sourceValue)) { + reader = readerMap.get(sourceValue); + + } else { + if (source.equals("file")) { + table = new FileTable(sourceValue, fRow, sChar, lChar); + } else if (source.equals("input")) { + table = new StringTable(sourceValue, fRow, sChar, lChar); + } + + if (nextRow.equals("random")) { + ArrayBlockingQueue queue = new ArrayBlockingQueue( + cacheCap); + reader = new RandomReader(queue, table); + } else if (nextRow.equals("sequence")) { + + ArrayBlockingQueue queue = new ArrayBlockingQueue( + cacheCap); + reader = new SequenceReader(queue, table); + } + readerMap.put(sourceValue, reader); + } + resultRow = reader.nextRow(); + objCache.put(sourceValue, resultRow); + return resultRow.cells.get(col); + } + + public void unreg(UUID id) { + + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_Table.xml b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_Table.xml new file mode 100644 index 00000000..15f7c4a6 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_Table.xml @@ -0,0 +1,19 @@ + + + + file + input + + + + + + + sequence + random + + + + + + diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_UniqueNumber.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_UniqueNumber.java new file mode 100644 index 00000000..24bcb320 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_UniqueNumber.java @@ -0,0 +1,12 @@ +package org.bench4q.agent.parameterization.impl; + +import java.util.UUID; + +public class Para_UniqueNumber { + int currentNumber = 0; + + synchronized String getNumber(UUID id) + { + return String.valueOf(currentNumber++); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_UserNameAndPassword.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_UserNameAndPassword.java new file mode 100644 index 00000000..736c83ec --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/Para_UserNameAndPassword.java @@ -0,0 +1,121 @@ +package org.bench4q.agent.parameterization.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class Para_UserNameAndPassword { + String[] Password = new String[] { "a", "b", "c", "d", "e" }; + String[] userName = new String[] { "http://www.baidu.com/", + "http://www.163.com/", "http://baike.baidu.com/", + "http://zhidao.baidu.com/", "http://www.sina.com.cn/" }; + UUID[] useUUID = new UUID[5]; + + Map posMap = new HashMap(); + ReentrantReadWriteLock mapRWLock = new ReentrantReadWriteLock(); + ReentrantReadWriteLock idposLock = new ReentrantReadWriteLock(); + + public String getUserName(UUID id) { + mapRWLock.readLock().lock(); + if (posMap.containsKey(id)) { + mapRWLock.readLock().unlock(); + return userName[posMap.get(id)]; + } + mapRWLock.readLock().unlock(); + + int vaildPos = -1; + int tryNum = 0; + while (vaildPos < 0 && tryNum < 100) { + tryNum++; + idposLock.readLock().lock(); + for (int i = 0; i < 5; i++) { + + if (useUUID[i] == null) { + vaildPos = i; + break; + } + } + idposLock.readLock().unlock(); + if (vaildPos < 0) { + try { + Thread.sleep(1000); + } catch (Exception ex) { + + } + } + } + + idposLock.writeLock().lock(); + useUUID[vaildPos] = id; + idposLock.writeLock().unlock(); + mapRWLock.writeLock().lock(); + posMap.put(id, vaildPos); + mapRWLock.writeLock().unlock(); + return userName[vaildPos]; + } + + public String getPassword(UUID id) { + mapRWLock.readLock().lock(); + if (posMap.containsKey(id)) { + mapRWLock.readLock().unlock(); + return Password[posMap.get(id)]; + } + mapRWLock.readLock().unlock(); + + int vaildPos = -1; + int tryNum = 0; + while (vaildPos < 0 && tryNum < 100) { + tryNum++; + idposLock.readLock().lock(); + for (int i = 0; i < 5; i++) { + + if (useUUID[i] == null) { + vaildPos = i; + break; + } + } + idposLock.readLock().unlock(); + if (vaildPos < 0) { + try { + Thread.sleep(1000); + } catch (Exception ex) { + + } + } + } + + idposLock.writeLock().lock(); + useUUID[vaildPos] = id; + idposLock.writeLock().unlock(); + mapRWLock.writeLock().lock(); + posMap.put(id, vaildPos); + mapRWLock.writeLock().unlock(); + return Password[vaildPos]; + } + + public void unreg(UUID id) { + try { + // System.out.println("1"); + mapRWLock.writeLock().lock(); + // System.out.println("2"); + int pos = posMap.get(id); + // System.out.println("3"); + posMap.remove(id); + // System.out.println("4"); + mapRWLock.writeLock().unlock(); + // System.out.println("5"); + idposLock.writeLock().lock(); + // System.out.println("6"); + useUUID[pos] = null; + idposLock.writeLock().unlock(); + } catch (Exception ex) { + System.out.println(ex.getClass().getName()); + System.out.println(ex.getMessage()); + System.out.println(ex.getStackTrace()); + mapRWLock.writeLock().unlock(); + idposLock.writeLock().unlock(); + } + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParameterThreadOption.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParameterThreadOption.java new file mode 100644 index 00000000..e4b79149 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParameterThreadOption.java @@ -0,0 +1,29 @@ +package org.bench4q.agent.parameterization.impl; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ParameterThreadOption { + public final ParameterThreadOption instance = new ParameterThreadOption(); + Map> optionMap = new HashMap>(); + private List all = Arrays.asList("crossThread", "inThread"); + // private List justIn = Arrays.asList("inThread"); + private List justCross = Arrays.asList("crossThread"); + + private ParameterThreadOption() { + + optionMap.put("Para_File", all); + optionMap.put("Para_IteratorNumber", justCross); + optionMap.put("Para_RandomNumber", all); + optionMap.put("Para_UniqueNumber", all); + optionMap.put("Para_UserNameAndPassword", justCross); + } + + public List getThreadOption(String classname) { + if (this.optionMap.containsKey(classname) == false) + return all; + return optionMap.get(classname); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParameterizationParser.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParameterizationParser.java new file mode 100644 index 00000000..ff6f6684 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParameterizationParser.java @@ -0,0 +1,53 @@ +package org.bench4q.agent.parameterization.impl; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +public class ParameterizationParser { + + public static String parse(String text, InstanceControler insCon) { + // Pattern pattern = Pattern.compile(""); + String result = ""; + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db + .parse(new InputSource(new StringReader(text))); + Element root = document.getDocumentElement(); + String className = root.getAttribute("class"); + String methodName = root.getAttribute("method"); + String argString = root.getAttribute("args"); + String type = root.getAttribute("type"); + String[] args = argString.split(","); + if (argString.trim().equals("")) + args = new String[0]; + + String name = root.getAttribute("name"); + result = insCon.getParameterByContext(name); + if (result != null) + return result; + if (type.equals("crossThread")) { + result = insCon.getParameter(name, getCurrentPackageFullName() + + "." + className, methodName, args); + } else if (type.equals("inThread")) { + result = insCon.instanceLevelGetParameter(name, className, + methodName, args); + } + + } catch (Exception ex) { + return text; + } + return result; + } + + private static String getCurrentPackageFullName() { + return ParameterizationParser.class.getName().substring(0, + ParameterizationParser.class.getName().lastIndexOf('.')); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParametersFactory.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParametersFactory.java new file mode 100644 index 00000000..13795e4e --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/parameterization/impl/ParametersFactory.java @@ -0,0 +1,57 @@ +package org.bench4q.agent.parameterization.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ParametersFactory { + private ParametersFactory() { + + }; + + static private final ParametersFactory instance = new ParametersFactory(); + static String lockObj = ""; + + static public ParametersFactory getInstance() { + return instance; + } + + private Map objMap = new HashMap(); + + public boolean containObj(String className) { + boolean ret = false; + mapRWLock.readLock().lock(); + ret = objMap.containsKey(className); + mapRWLock.readLock().unlock(); + return ret; + } + + public Object getObj(String className) { + Object result = null; + mapRWLock.readLock().lock(); + result = objMap.get(className); + mapRWLock.readLock().unlock(); + return result; + } + + private String rootFilePath = "/home/yxsh/git/Bench4Q-Agent/parameterClass/"; + + ReentrantReadWriteLock mapRWLock = new ReentrantReadWriteLock(); + + public boolean createObj(String className) { + try { + MyFileClassLoader cl = new MyFileClassLoader(); + cl.setClassPath(rootFilePath); + Class cls = cl.loadClass(className); + Object instance = cls.newInstance(); + mapRWLock.writeLock().lock(); + objMap.put(className, instance); + + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } + mapRWLock.writeLock().unlock(); + return true; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Behavior.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Behavior.java new file mode 100644 index 00000000..ad20e417 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Behavior.java @@ -0,0 +1,12 @@ +package org.bench4q.agent.plugin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Behavior { + String value(); +} \ No newline at end of file diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/BehaviorInfo.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/BehaviorInfo.java new file mode 100644 index 00000000..d09d4b88 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/BehaviorInfo.java @@ -0,0 +1,23 @@ +package org.bench4q.agent.plugin; + +public class BehaviorInfo { + private String name; + private ParameterInfo[] parameters; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ParameterInfo[] getParameters() { + return parameters; + } + + public void setParameters(ParameterInfo[] parameters) { + this.parameters = parameters; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/ClassHelper.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/ClassHelper.java new file mode 100644 index 00000000..950bab2f --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/ClassHelper.java @@ -0,0 +1,124 @@ +package org.bench4q.agent.plugin; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import org.springframework.stereotype.Component; + +@Component +public class ClassHelper { + + public List getClassNames(String packageName, + boolean searchInChildPackage) { + try { + List classNames = new ArrayList(); + URLClassLoader classLoader = (URLClassLoader) Thread + .currentThread().getContextClassLoader(); + URL[] urls = classLoader.getURLs(); + for (URL url : urls) { + if (url.getProtocol().equals("file")) { + File file = new File(url.getFile()); + String root = file.getPath().replace("\\", "/"); + if (file.isDirectory()) { + classNames.addAll(this.getClassNamesFromDirectory(root, + packageName, searchInChildPackage, file, true)); + } else if (file.getName().endsWith(".jar")) { + classNames.addAll(this.getClassNameFromJar(packageName, + searchInChildPackage, file)); + } + } + } + return classNames; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private List getClassNamesFromDirectory(String root, + String packageName, boolean searchInChildPackage, File directory, + boolean continueSearch) { + List classNames = new ArrayList(); + File[] files = directory.listFiles(); + for (File file : files) { + String filePath = file.getPath().replace("\\", "/"); + if (file.isDirectory()) { + if (searchInChildPackage || continueSearch) { + boolean needToContinue = continueSearch; + if (filePath.endsWith(packageName.replace(".", "/"))) { + needToContinue = needToContinue & false; + } + classNames.addAll(this.getClassNamesFromDirectory(root, + packageName, searchInChildPackage, file, + needToContinue)); + } + } else { + if (filePath.endsWith(".class")) { + String classFileName = filePath.replace(root + "/", ""); + if (classFileName.startsWith(packageName.replace(".", "/"))) { + String className = classFileName.substring(0, + classFileName.length() - ".class".length()) + .replace("/", "."); + classNames.add(className); + } + } + } + } + return classNames; + } + + private List getClassNameFromJar(String packageName, + boolean searchInChildPackage, File file) { + List classNames = new ArrayList(); + JarFile jarFile = null; + try { + jarFile = new JarFile(file); + Enumeration jarEntries = jarFile.entries(); + while (jarEntries.hasMoreElements()) { + JarEntry jarEntry = jarEntries.nextElement(); + String entryName = jarEntry.getName(); + if (entryName.endsWith(".class")) { + String packagePath = packageName.replace(".", "/"); + if (searchInChildPackage) { + if (entryName.startsWith(packagePath)) { + entryName = entryName.replace("/", ".").substring( + 0, entryName.lastIndexOf(".")); + classNames.add(entryName); + } + } else { + int index = entryName.lastIndexOf("/"); + String entryPath; + if (index != -1) { + entryPath = entryName.substring(0, index); + } else { + entryPath = entryName; + } + if (entryPath.equals(packagePath)) { + entryName = entryName.replace("/", ".").substring( + 0, entryName.lastIndexOf(".")); + classNames.add(entryName); + } + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (jarFile != null) { + try { + jarFile.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return classNames; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Parameter.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Parameter.java new file mode 100644 index 00000000..a9e0a171 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Parameter.java @@ -0,0 +1,12 @@ +package org.bench4q.agent.plugin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface Parameter { + String value(); +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/ParameterInfo.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/ParameterInfo.java new file mode 100644 index 00000000..4db0e540 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/ParameterInfo.java @@ -0,0 +1,23 @@ +package org.bench4q.agent.plugin; + +public class ParameterInfo { + private String name; + private String type; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Plugin.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Plugin.java new file mode 100644 index 00000000..4647553c --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/Plugin.java @@ -0,0 +1,12 @@ +package org.bench4q.agent.plugin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Plugin { + String value(); +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/PluginInfo.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/PluginInfo.java new file mode 100644 index 00000000..aadc176a --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/PluginInfo.java @@ -0,0 +1,32 @@ +package org.bench4q.agent.plugin; + +public class PluginInfo { + private String name; + private ParameterInfo[] parameters; + private BehaviorInfo[] behaviors; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ParameterInfo[] getParameters() { + return parameters; + } + + public void setParameters(ParameterInfo[] parameters) { + this.parameters = parameters; + } + + public BehaviorInfo[] getBehaviors() { + return behaviors; + } + + public void setBehaviors(BehaviorInfo[] behaviors) { + this.behaviors = behaviors; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/PluginManager.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/PluginManager.java new file mode 100644 index 00000000..735d3a37 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/PluginManager.java @@ -0,0 +1,269 @@ +package org.bench4q.agent.plugin; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.bench4q.agent.share.DealWithLog; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class PluginManager { + private ClassHelper classHelper; + private TypeConverter typeConverter; + private Map> plugins; + private Logger logger = Logger.getLogger(PluginManager.class); + + @Autowired + public PluginManager(ClassHelper classHelper, TypeConverter typeConverter) { + this.setClassHelper(classHelper); + this.setTypeConverter(typeConverter); + this.setPlugins(this.loadPlugins("org.bench4q.agent.plugin")); + } + + private ClassHelper getClassHelper() { + return classHelper; + } + + private void setClassHelper(ClassHelper classHelper) { + this.classHelper = classHelper; + } + + private TypeConverter getTypeConverter() { + return typeConverter; + } + + private void setTypeConverter(TypeConverter typeConverter) { + this.typeConverter = typeConverter; + } + + public Map> getPlugins() { + return plugins; + } + + private void setPlugins(Map> plugins) { + this.plugins = plugins; + } + + public Map> loadPlugins(String packageName) { + try { + List classNames = this.getClassHelper().getClassNames( + packageName, true); + Map> ret = new HashMap>(); + for (String className : classNames) { + Class plugin = Class.forName(className); + if (plugin.isAnnotationPresent(Plugin.class)) { + ret.put(plugin.getAnnotation(Plugin.class).value(), plugin); + } + } + return ret; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public List getPluginInfo() { + try { + Map> plugins = this.getPlugins(); + List ret = new ArrayList(); + for (Class plugin : plugins.values()) { + PluginInfo pluginInfo = new PluginInfo(); + pluginInfo + .setName((plugin.getAnnotation(Plugin.class)).value()); + pluginInfo.setParameters(this.getParameters(plugin + .getConstructors()[0])); + Method[] behaviors = this.getBehaviors(plugin); + pluginInfo.setBehaviors(new BehaviorInfo[behaviors.length]); + int i = 0; + for (i = 0; i < behaviors.length; i++) { + Method behaviorMethod = behaviors[i]; + BehaviorInfo behaviorInfo = buildBehaviorInfo(behaviorMethod); + pluginInfo.getBehaviors()[i] = behaviorInfo; + } + ret.add(pluginInfo); + } + return ret; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private BehaviorInfo buildBehaviorInfo(Method behaviorMethod) + throws ClassNotFoundException { + BehaviorInfo behaviorInfo = new BehaviorInfo(); + behaviorInfo.setName((behaviorMethod.getAnnotation(Behavior.class)) + .value()); + behaviorInfo.setParameters(this.getParameters(behaviorMethod)); + return behaviorInfo; + } + + private ParameterInfo[] getParameters(Method behavior) { + try { + int parameterCount = behavior.getParameterTypes().length; + Annotation[][] parameterAnnotations = behavior + .getParameterAnnotations(); + ParameterInfo[] parameterNames = new ParameterInfo[parameterCount]; + int i; + for (i = 0; i < parameterCount; i++) { + Annotation[] annotations = parameterAnnotations[i]; + Parameter parameter = (Parameter) annotations[0]; + Class type = behavior.getParameterTypes()[i]; + ParameterInfo parameterInfo = buildParameterInfo( + parameter.value(), type.getName()); + parameterNames[i] = parameterInfo; + } + return parameterNames; + } catch (Exception e) { + logger.error(DealWithLog.getExceptionStackTrace(e)); + return null; + } + } + + private ParameterInfo[] getParameters(Constructor behavior) { + try { + int parameterCount = behavior.getParameterTypes().length; + Annotation[][] parameterAnnotations = behavior + .getParameterAnnotations(); + ParameterInfo[] parameterNames = new ParameterInfo[parameterCount]; + int i; + for (i = 0; i < parameterCount; i++) { + Annotation[] annotations = parameterAnnotations[i]; + Parameter parameter = (Parameter) annotations[0]; + Class type = behavior.getParameterTypes()[i]; + ParameterInfo parameterInfo = buildParameterInfo( + parameter.value(), type.getName()); + parameterNames[i] = parameterInfo; + } + return parameterNames; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private ParameterInfo buildParameterInfo(String name, String type) { + ParameterInfo parameterInfo = new ParameterInfo(); + parameterInfo.setName(name); + parameterInfo.setType(type); + return parameterInfo; + } + + private Method[] getBehaviors(Class plugin) { + try { + Method[] methods = plugin.getMethods(); + List ret = new ArrayList(); + int i = 0; + for (i = 0; i < methods.length; i++) { + if (methods[i].isAnnotationPresent(Behavior.class)) { + ret.add(methods[i]); + } + } + return ret.toArray(new Method[0]); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public Object initializePlugin(Class plugin, + Map parameters) { + try { + Constructor[] ctConstructors = plugin.getConstructors(); + if (ctConstructors.length != 1) { + return null; + } + Constructor constructor = ctConstructors[0]; + Object[] params = prepareParameters(constructor, parameters); + return plugin.getConstructors()[0].newInstance(params); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private Object[] prepareParameters(Constructor behavior, + Map parameters) { + try { + ParameterInfo[] parameterInfo = this.getParameters(behavior); + Object values[] = new Object[parameterInfo.length]; + int i = 0; + for (i = 0; i < parameterInfo.length; i++) { + Object value = parameters.get(parameterInfo[i].getName()); + if (value == null) { + values[i] = null; + } else { + values[i] = this.getTypeConverter().convert(value, + parameterInfo[i].getType()); + } + } + return values; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private Object[] prepareParameters(Method behavior, + Map parameters) { + try { + ParameterInfo[] parameterInfo = this.getParameters(behavior); + Object values[] = new Object[parameterInfo.length]; + int i = 0; + for (i = 0; i < parameterInfo.length; i++) { + Object value = parameters.get(parameterInfo[i].getName()); + if (value == null) { + values[i] = null; + } else { + values[i] = this.getTypeConverter().convert(value, + parameterInfo[i].getType()); + } + } + return values; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public Object doBehavior(Object plugin, String behaviorName, + Map parameters) { + try { + Method method = findMethod(plugin, behaviorName); + if (method == null) { + return null; + } + Object[] params = prepareParameters(method, parameters); + return method.invoke(plugin, params); + } catch (Exception e) { + + return null; + } + } + + private Method findMethod(Object plugin, String behaviorName) { + try { + Method[] methods = plugin.getClass().getMethods(); + int i = 0; + for (i = 0; i < methods.length; i++) { + if (methods[i].isAnnotationPresent(Behavior.class)) { + if (((Behavior) methods[i].getAnnotation(Behavior.class)) + .value().equals(behaviorName)) { + return methods[i]; + } + } + } + return null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/TypeConverter.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/TypeConverter.java new file mode 100644 index 00000000..8b6b29b0 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/TypeConverter.java @@ -0,0 +1,44 @@ +package org.bench4q.agent.plugin; + +import org.springframework.stereotype.Component; + +@Component +public class TypeConverter { + public Object convert(Object source, String targetClassName) { + if (targetClassName.equals("boolean")) { + return Boolean.parseBoolean(source.toString()); + } + if (targetClassName.equals("char")) { + return source.toString().toCharArray()[0]; + } + if (targetClassName.equals("byte")) { + return Byte.parseByte(source.toString()); + } + if (targetClassName.equals("short")) { + return Short.parseShort(source.toString()); + } + if (targetClassName.equals("int")) { + return Integer.parseInt(source.toString()); + } + if (targetClassName.equals("long")) { + return Long.parseLong(source.toString()); + } + if (targetClassName.equals("float")) { + return Float.parseFloat(source.toString()); + } + if (targetClassName.equals("double")) { + return Double.parseDouble(source.toString()); + } + + try { + Class targetClass = Class.forName(targetClassName); + if (targetClass.isAssignableFrom(String.class)) { + return source.toString(); + } + return targetClass.cast(source); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/CommandLinePlugin.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/CommandLinePlugin.java new file mode 100644 index 00000000..97072a39 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/CommandLinePlugin.java @@ -0,0 +1,89 @@ +package org.bench4q.agent.plugin.basic; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import org.bench4q.agent.plugin.Behavior; +import org.bench4q.agent.plugin.Parameter; +import org.bench4q.agent.plugin.Plugin; +import org.bench4q.agent.plugin.result.CommandLineReturn; + +@Plugin("CommandLine") +public class CommandLinePlugin { + private String standardOutput; + private String standardError; + + public String getStandardOutput() { + return standardOutput; + } + + private void setStandardOutput(String standardOutput) { + this.standardOutput = standardOutput; + } + + public String getStandardError() { + return standardError; + } + + private void setStandardError(String standardError) { + this.standardError = standardError; + } + + public CommandLinePlugin() { + + } + + @Behavior("Command") + public CommandLineReturn command(@Parameter("command") String command) { + try { + final Process process = Runtime.getRuntime().exec(command); + new Thread() { + public void run() { + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream())); + String streamline = ""; + try { + setStandardOutput(""); + while ((streamline = reader.readLine()) != null) { + setStandardOutput(getStandardOutput() + + streamline + + System.getProperty("line.separator")); + } + } finally { + reader.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }.start(); + new Thread() { + public void run() { + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getErrorStream())); + String streamline = ""; + try { + setStandardError(""); + while ((streamline = reader.readLine()) != null) { + setStandardError(getStandardError() + + streamline + + System.getProperty("line.separator")); + } + } finally { + reader.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }.start(); + process.waitFor(); + return new CommandLineReturn(true); + } catch (Exception e) { + e.printStackTrace(); + return new CommandLineReturn(false); + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/ConstantTimerPlugin.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/ConstantTimerPlugin.java new file mode 100644 index 00000000..589d0b40 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/ConstantTimerPlugin.java @@ -0,0 +1,27 @@ +package org.bench4q.agent.plugin.basic; + +import org.apache.log4j.Logger; +import org.bench4q.agent.plugin.Behavior; +import org.bench4q.agent.plugin.Parameter; +import org.bench4q.agent.plugin.Plugin; +import org.bench4q.agent.plugin.result.TimerReturn; + +@Plugin("ConstantTimer") +public class ConstantTimerPlugin { + private Logger logger = Logger.getLogger(ConstantTimerPlugin.class); + + public ConstantTimerPlugin() { + + } + + @Behavior("Sleep") + public TimerReturn sleep(@Parameter("time") int time) { + try { + Thread.sleep(time); + return new TimerReturn(true); + } catch (Exception e) { + logger.info("sleep interrupted!"); + return new TimerReturn(false); + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/LogPlugin.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/LogPlugin.java new file mode 100644 index 00000000..473ef163 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/LogPlugin.java @@ -0,0 +1,19 @@ +package org.bench4q.agent.plugin.basic; + +import org.bench4q.agent.plugin.Behavior; +import org.bench4q.agent.plugin.Parameter; +import org.bench4q.agent.plugin.Plugin; +import org.bench4q.agent.plugin.result.LogReturn; + +@Plugin("Log") +public class LogPlugin { + public LogPlugin() { + + } + + @Behavior("Log") + public LogReturn log(@Parameter("message") String message) { + System.out.println(message); + return new LogReturn(true); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/http/HttpPlugin.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/http/HttpPlugin.java new file mode 100644 index 00000000..3d41a5d9 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/http/HttpPlugin.java @@ -0,0 +1,339 @@ +/* + * Author Coderfengyun + * + * And th parmas has some special split. + * Like, QueryParams and bodyParams should be split by ';' + * And Headers should be split by '|;' + */ +package org.bench4q.agent.plugin.basic.http; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.httpclient.Cookie; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.DeleteMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.bench4q.agent.plugin.Behavior; +import org.bench4q.agent.plugin.Parameter; +import org.bench4q.agent.plugin.Plugin; +import org.bench4q.agent.plugin.result.HttpReturn; +import org.bench4q.agent.scenario.util.ParameterParser; +import org.bench4q.agent.scenario.util.Table; + +@Plugin("Http") +public class HttpPlugin { + private HttpClient httpClient; + + public HttpClient getHttpClient() { + return httpClient; + } + + private void setHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public HttpPlugin() { + this.setHttpClient(new HttpClient()); + } + + void setHeaders(HttpMethod method, String headers) { + if (headers != null) { + List nvPairs = parseHeaders(headers); + for (NameValuePair nv : nvPairs) { + method.addRequestHeader(nv.getName(), nv.getValue()); + } + // New add + String cookieValue = ""; + for (Cookie cookie : this.getHttpClient().getState().getCookies()) { + if (!cookieValue.isEmpty()) { + cookieValue += ";"; + } + cookieValue += cookie.getName() + "=" + cookie.getValue(); + } + if (!cookieValue.isEmpty()) { + method.addRequestHeader("Cookie", cookieValue); + } + } + } + + List parseHeaders(String value) { + List nvPairs = new LinkedList(); + Table headerTable = ParameterParser.buildTable(value, + new LinkedList() { + private static final long serialVersionUID = 3498984411571605459L; + { + add("header"); + add("value"); + } + }); + for (List entry : headerTable.getRealContent()) { + if (entry.size() != headerTable.getColumnCount()) { + continue; + } + nvPairs.add(new NameValuePair(entry.get(0).trim(), entry.get(1) + .trim())); + } + return nvPairs; + } + + private static NameValuePair[] setInputParameters( + List inputParameters) { + Set res = new HashSet(); + Iterator paramIter = inputParameters.iterator(); + + while (paramIter.hasNext()) { + String token = paramIter.next(); + int index = token.indexOf('='); + res.add(new NameValuePair(token.substring(0, index), token + .substring(index + 1))); + } + return res.toArray(new NameValuePair[res.size()]); + } + + private static String completeUri(String uri) { + String scheme = uri.substring(0, 5); + if (!scheme.equals("http:") && !scheme.equals("https")) + uri = "http://" + uri; + return uri; + } + + /** + * + * @param url + * @param queryParams + * (NField) QueryParams should be split by ';' + * @param headers + * (Table)has two columns, such as header and value + * + * @param respVarsToSaveInSession + * (Table) has four columns, such as varName, + * varRegularExpression, leftBoundry, and rightBoundry + * @return + */ + @Behavior("Get") + public HttpReturn get(@Parameter("url") String url, + @Parameter("queryParams") String queryParams, + @Parameter("headers") String headers, + @Parameter("respVarsToSaveInSession") String respVarsToSaveInSession) { + + GetMethod method = new GetMethod(completeUri(url)); + if (isValid(queryParams)) { + method.setQueryString(queryParams); + } + setHeaders(method, headers); + method.getParams().makeLenient(); + method.setFollowRedirects(false); + return excuteMethod(method, respVarsToSaveInSession); + } + + private HttpReturn excuteMethod(HttpMethod method, + String respVarsToSaveInSession) { + int responseCode = -1; + long contentLength = 0; + String contentType = ""; + Map respVars = new LinkedHashMap(); + + try { + responseCode = this.getHttpClient().executeMethod(method); + method.getStatusLine().toString(); + Header[] responseHeaders = method.getResponseHeaders(); + if (method.getResponseHeader("Content-Length") != null) { + contentLength = Long.parseLong(method.getResponseHeader( + "Content-Length").getValue()); + } + if (method.getResponseHeader("Content-Type") != null) { + contentType = method.getResponseHeader("Content-Type") + .getValue(); + } + if (isValid(respVarsToSaveInSession)) { + respVars = doExtractResponseVariables(respVarsToSaveInSession, + method.getResponseBodyAsString()); + } + return new HttpReturn(responseCode > 0, responseCode, + contentLength, contentType, responseHeaders, respVars); + } catch (HttpException e) { + e.printStackTrace(); + return new HttpReturn(false, 400, contentLength, contentType); + } catch (IOException e) { + e.printStackTrace(); + return new HttpReturn(false, 400, contentLength, contentType); + } finally { + method.releaseConnection(); + } + } + + private Map doExtractResponseVariables( + String respVarsToSaveInSession, String responseBodyAsString) { + Map keyValues = new LinkedHashMap(); + List> varExtractExpressionList = ParameterParser + .buildTable(respVarsToSaveInSession, new LinkedList() { + private static final long serialVersionUID = -923211006660227362L; + { + add("varName"); + add("varRegularExpression"); + add("leftBoundry"); + add("rightBoundry"); + } + }).getRealContent(); + for (List row : varExtractExpressionList) { + keyValues.putAll(doExtractParamByRow(row, responseBodyAsString)); + } + return keyValues; + } + + private Map doExtractParamByRow(List row, + String responseBody) { + Map result = new LinkedHashMap(); + if (row.size() <= 3) { + return result; + } + String varName = row.get(0); + String varExpression = row.get(1); + String varLeftBoundry = row.get(2); + String varRightBoundry = row.get(3); + + if (!isValid(varExpression)) { + result.put( + varName, + extractExactlyValueWith(varLeftBoundry, varRightBoundry, + responseBody)); + return result; + } + + Matcher matcher = Pattern.compile(varExpression).matcher(responseBody); + if (!matcher.find()) { + result.put( + varName, + extractExactlyValueWith(varLeftBoundry, varRightBoundry, + responseBody)); + return result; + } + result.put( + varName, + extractExactlyValueWith(varLeftBoundry, varRightBoundry, + matcher.group())); + return result; + } + + private String extractExactlyValueWith(String varLeftBoundry, + String varRightBoundry, String matchedVariable) { + int indexOfLB = matchedVariable.indexOf(varLeftBoundry); + int indexOfRB = matchedVariable.indexOf(varRightBoundry); + return matchedVariable.substring(indexOfLB + varLeftBoundry.length(), + indexOfRB); + } + + /** + * + * @param url + * @param queryParams + * @param headers + * @param bodyContent + * , when the Content-Length in header G.T. zero, then use this + * @param bodyParams + * , else use this + * @return + */ + @Behavior("Post") + public HttpReturn post(@Parameter("url") String url, + @Parameter("queryParams") String queryParams, + @Parameter("headers") String headers, + @Parameter("bodyContent") String bodyContent, + @Parameter("bodyparameters") String bodyParams, + @Parameter("respVarsToSaveInSession") String respVarToSaveInSession) { + PostMethod method = new PostMethod(completeUri(url)); + setHeaders(method, headers); + if (isValid(queryParams)) { + method.setQueryString(setInputParameters(ParameterParser + .buildNField(queryParams))); + } + if (isValid(bodyParams)) { + method.setRequestBody(setInputParameters(ParameterParser + .buildNField(bodyParams))); + } + String contentType = getMethodContentType(method); + if (isValid(bodyContent) && isValid(contentType)) { + try { + method.setRequestEntity(new StringRequestEntity(bodyContent, + contentType, null)); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + method.getParams().makeLenient(); + method.setFollowRedirects(false); + return excuteMethod(method, respVarToSaveInSession); + } + + private String getMethodContentType(HttpMethod method) { + Header contentTypeHeader = method.getRequestHeader("Content-Type"); + String contentType = null; + if (contentTypeHeader != null + && !contentTypeHeader.toExternalForm().isEmpty()) { + contentType = contentTypeHeader.toExternalForm(); + } + return contentType; + } + + private boolean isValid(String content) { + return content != null && content.length() != 0; + } + + @Behavior("Put") + public HttpReturn put(@Parameter("url") String url, + @Parameter("queryParams") String queryParams, + @Parameter("headers") String headers, + @Parameter("bodyContent") String bodyContent, + @Parameter("bodyparameters") String bodyParams, + @Parameter("respVarsToSaveInSession") String respVarToSaveInSession) { + PutMethod method = new PutMethod(completeUri(url)); + setHeaders(method, headers); + if (isValid(queryParams)) { + method.setQueryString(setInputParameters(ParameterParser + .buildNField(queryParams))); + } + String contentType = getMethodContentType(method); + if (isValid(bodyContent) && isValid(contentType)) { + try { + method.setRequestEntity(new StringRequestEntity(bodyContent, + contentType, null)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + method.getParams().makeLenient(); + return excuteMethod(method, respVarToSaveInSession); + } + + @Behavior("Delete") + public HttpReturn delete(@Parameter("url") String url, + @Parameter("queryParams") String queryParams, + @Parameter("headers") String headers, + @Parameter("respVarsToSaveInSession") String respVarToSaveInSession) { + DeleteMethod method = new DeleteMethod(completeUri(url)); + setHeaders(method, headers); + if (isValid(queryParams)) { + method.setQueryString(setInputParameters(ParameterParser + .buildNField(queryParams))); + } + method.getParams().makeLenient(); + return excuteMethod(method, respVarToSaveInSession); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/http/ParameterConstant.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/http/ParameterConstant.java new file mode 100644 index 00000000..691565f5 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/basic/http/ParameterConstant.java @@ -0,0 +1,5 @@ +package org.bench4q.agent.plugin.basic.http; + +public class ParameterConstant { + public static final String escape = "\\"; +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/CommandLineReturn.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/CommandLineReturn.java new file mode 100644 index 00000000..15679f69 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/CommandLineReturn.java @@ -0,0 +1,7 @@ +package org.bench4q.agent.plugin.result; + +public class CommandLineReturn extends PluginReturn { + public CommandLineReturn(boolean success) { + this.setSuccess(success); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/HttpReturn.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/HttpReturn.java new file mode 100644 index 00000000..bee2dcce --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/HttpReturn.java @@ -0,0 +1,66 @@ +package org.bench4q.agent.plugin.result; + +import java.util.Map; + +import org.apache.commons.httpclient.Header; + +/*** + * the contentLength's unit is Byte + * + * @author coderfengyun + * + */ +public class HttpReturn extends PluginReturn { + private int statusCode; + private long contentLength; + private String contentType; + private Header[] headers; + + public int getStatusCode() { + return statusCode; + } + + private void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + public long getContentLength() { + return contentLength; + } + + private void setContentLength(long contentLength) { + this.contentLength = contentLength; + } + + public String getContentType() { + return contentType; + } + + private void setContentType(String contentType) { + this.contentType = contentType; + } + + public Header[] getHeaders() { + return headers; + } + + private void setHeaders(Header[] headers) { + this.headers = headers; + } + + public HttpReturn(boolean success, int statusCode, long contentLength, + String contentType) { + this.setSuccess(success); + this.setStatusCode(statusCode); + this.setContentLength(contentLength); + this.setContentType(contentType); + } + + public HttpReturn(boolean success, int responseCode, long contentLength2, + String contentType2, Header[] responseHeaders, + Map runTimeParams) { + this(success, responseCode, contentLength2, contentType2); + this.setHeaders(responseHeaders); + this.getRunTimeParams().putAll(runTimeParams); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/LogReturn.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/LogReturn.java new file mode 100644 index 00000000..d26ff1eb --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/LogReturn.java @@ -0,0 +1,7 @@ +package org.bench4q.agent.plugin.result; + +public class LogReturn extends PluginReturn { + public LogReturn(boolean success) { + this.setSuccess(success); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/PluginReturn.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/PluginReturn.java new file mode 100644 index 00000000..b931dcb0 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/PluginReturn.java @@ -0,0 +1,29 @@ +package org.bench4q.agent.plugin.result; + +import java.util.LinkedHashMap; +import java.util.Map; + +public abstract class PluginReturn { + private boolean success; + private Map runTimeParams; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public Map getRunTimeParams() { + return runTimeParams; + } + + public void setRunTimeParams(Map runTimeParams) { + this.runTimeParams = runTimeParams; + } + + public PluginReturn() { + this.setRunTimeParams(new LinkedHashMap()); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/TimerReturn.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/TimerReturn.java new file mode 100644 index 00000000..9f3ecad0 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/plugin/result/TimerReturn.java @@ -0,0 +1,12 @@ +package org.bench4q.agent.plugin.result; + +/** + * + * @author coderfengyun + * + */ +public class TimerReturn extends PluginReturn { + public TimerReturn(boolean success) { + this.setSuccess(success); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Batch.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Batch.java new file mode 100644 index 00000000..f05a3a2f --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Batch.java @@ -0,0 +1,43 @@ +package org.bench4q.agent.scenario; + +import org.bench4q.agent.scenario.behavior.Behavior; + +public class Batch { + private int id; + private int parentId; + private int childId; + private Behavior[] behaviors; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getParentId() { + return parentId; + } + + public void setParentId(int parentId) { + this.parentId = parentId; + } + + public int getChildId() { + return childId; + } + + public void setChildId(int childId) { + this.childId = childId; + } + + public Behavior[] getBehaviors() { + return behaviors; + } + + public void setBehaviors(Behavior[] behaviors) { + this.behaviors = behaviors; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/BehaviorResult.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/BehaviorResult.java new file mode 100644 index 00000000..3311f076 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/BehaviorResult.java @@ -0,0 +1,125 @@ +package org.bench4q.agent.scenario; + +import java.util.Date; + +public class BehaviorResult { + private String pluginId; + private String pluginName; + private String behaviorName; + private Date startDate; + private Date endDate; + private long responseTime; + private boolean success; + + private int behaviorId; + private String behaviorUrl; + private long contentLength; + private int statusCode; + private String contentType; + private boolean shouldBeCountResponseTime; + + public String getPluginId() { + return pluginId; + } + + public void setPluginId(String pluginId) { + this.pluginId = pluginId; + } + + public String getPluginName() { + return pluginName; + } + + public void setPluginName(String pluginName) { + this.pluginName = pluginName; + } + + public String getBehaviorName() { + return behaviorName; + } + + public void setBehaviorName(String behaviorName) { + this.behaviorName = behaviorName; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public long getResponseTime() { + return responseTime; + } + + public void setResponseTime(long responseTime) { + this.responseTime = responseTime; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public int getBehaviorId() { + return behaviorId; + } + + public void setBehaviorId(int behaviorId) { + this.behaviorId = behaviorId; + } + + public String getBehaviorUrl() { + return behaviorUrl; + } + + public void setBehaviorUrl(String behaviorUrl) { + this.behaviorUrl = behaviorUrl; + } + + public long getContentLength() { + return contentLength; + } + + public void setContentLength(long contentLength) { + this.contentLength = contentLength; + } + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + public String getContentType() { + return contentType; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public boolean isShouldBeCountResponseTime() { + return shouldBeCountResponseTime; + } + + public void setShouldBeCountResponseTime(boolean shouldBeCountResponseTime) { + this.shouldBeCountResponseTime = shouldBeCountResponseTime; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Page.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Page.java new file mode 100644 index 00000000..f03f9e77 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Page.java @@ -0,0 +1,22 @@ +package org.bench4q.agent.scenario; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.PageResultCollector; + +public class Page { + private Batch[] batches; + final private DataCollector dataCollector = new PageResultCollector(); + + public Batch[] getBatches() { + return batches; + } + + public void setBatches(Batch[] batches) { + this.batches = batches; + } + + public DataCollector getDataCollector() { + return dataCollector; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/PageResult.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/PageResult.java new file mode 100644 index 00000000..fcadd468 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/PageResult.java @@ -0,0 +1,77 @@ +package org.bench4q.agent.scenario; + +import java.util.ArrayList; +import java.util.List; + +public class PageResult { + private int pageId; + private long pageStartTime; + private long pageEndTime; + private long executeRange; + + public int getPageId() { + return pageId; + } + + private void setPageId(int pageId) { + this.pageId = pageId; + } + + public long getPageStartTime() { + return pageStartTime; + } + + private void setPageStartTime(long pageStartTime) { + this.pageStartTime = pageStartTime; + } + + public long getPageEndTime() { + return pageEndTime; + } + + private void setPageEndTime(long pageEndTime) { + this.pageEndTime = pageEndTime; + } + + public long getExecuteRange() { + return executeRange; + } + + private void setExecuteRange(long executeRange) { + this.executeRange = executeRange; + } + + private PageResult() { + init(); + } + + private void init() { + this.setPageStartTime(Long.MAX_VALUE); + this.setPageEndTime(Long.MIN_VALUE); + this.setExecuteRange(0); + } + + public static PageResult buildPageResult(int pageId, + List behaviorResults) { + PageResult result = new PageResult(); + result.setPageId(pageId); + if (behaviorResults == null) { + behaviorResults = new ArrayList(); + } + for (BehaviorResult behaviorResult : behaviorResults) { + if (behaviorResult.getStartDate().getTime() < result + .getPageStartTime()) { + result.setPageStartTime(behaviorResult.getStartDate().getTime()); + } + if (behaviorResult.getEndDate().getTime() > result.getPageEndTime()) { + result.setPageEndTime(behaviorResult.getEndDate().getTime()); + } + // Page excuteRange rely on the behaviors' execute way, if it's + // executed in batch, i should take the longest behavior in batch + // to calculate this One. + } + result.setExecuteRange(result.getPageEndTime() + - result.getPageStartTime()); + return result; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Parameter.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Parameter.java new file mode 100644 index 00000000..10785505 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Parameter.java @@ -0,0 +1,23 @@ +package org.bench4q.agent.scenario; + +public class Parameter { + private String key; + private String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Scenario.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Scenario.java new file mode 100644 index 00000000..04983540 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Scenario.java @@ -0,0 +1,176 @@ +package org.bench4q.agent.scenario; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.bench4q.agent.scenario.behavior.Behavior; +import org.bench4q.agent.scenario.behavior.BehaviorFactory; +import org.bench4q.share.helper.MarshalHelper; +import org.bench4q.share.models.agent.ParameterModel; +import org.bench4q.share.models.agent.RunScenarioModel; +import org.bench4q.share.models.agent.scriptrecord.BatchModel; +import org.bench4q.share.models.agent.scriptrecord.BehaviorModel; +import org.bench4q.share.models.agent.scriptrecord.PageModel; +import org.bench4q.share.models.agent.scriptrecord.UsePluginModel; + +public class Scenario { + private UsePlugin[] usePlugins; + private Page[] pages; + private List behaviors; + + public UsePlugin[] getUsePlugins() { + return usePlugins; + } + + public void setUsePlugins(UsePlugin[] usePlugins) { + this.usePlugins = usePlugins; + } + + public Page[] getPages() { + return pages; + } + + public void setPages(Page[] pages) { + this.pages = pages; + } + + private List getBehaviors() { + return behaviors; + } + + private void setBehaviors(List behaviors) { + this.behaviors = behaviors; + } + + public Scenario() { + this.setBehaviors(new ArrayList()); + } + + public List getAllBehaviorsInScenario() { + if (this.getBehaviors().size() > 0) { + return Collections.unmodifiableList(this.getBehaviors()); + } + List behaviors = new ArrayList(); + for (Page page : this.getPages()) { + for (Batch batch : page.getBatches()) { + for (Behavior behavior : batch.getBehaviors()) { + behaviors.add(behavior); + } + } + } + return Collections.unmodifiableList(behaviors); + } + + public static Scenario scenarioBuilder(String scenarioContent) { + return extractScenario((RunScenarioModel) MarshalHelper.tryUnmarshal( + RunScenarioModel.class, scenarioContent)); + } + + public static Scenario scenarioBuilder(RunScenarioModel scenarioModel) { + if (scenarioModel == null) { + throw new NullPointerException(); + } + Scenario scenario = extractScenario(scenarioModel); + return scenario; + } + + private static Scenario extractScenario(RunScenarioModel runScenarioModel) { + Scenario scenario = new Scenario(); + scenario.setUsePlugins(new UsePlugin[runScenarioModel.getUsePlugins() + .size()]); + scenario.setPages(new Page[runScenarioModel.getPages().size()]); + extractUsePlugins(runScenarioModel, scenario); + extractPages(runScenarioModel, scenario); + return scenario; + } + + private static void extractPages(RunScenarioModel runScenarioModel, + Scenario scenario) { + List pageModels = runScenarioModel.getPages(); + for (int i = 0; i < pageModels.size(); i++) { + PageModel pageModel = pageModels.get(i); + scenario.getPages()[i] = extractPage(pageModel); + } + } + + private static Page extractPage(PageModel pageModel) { + Page page = new Page(); + page.setBatches(new Batch[pageModel.getBatches().size()]); + List batches = pageModel.getBatches(); + for (int i = 0; i < pageModel.getBatches().size(); i++) { + BatchModel batch = batches.get(i); + page.getBatches()[i] = extractBatch(batch); + } + return page; + } + + private static Batch extractBatch(BatchModel batchModel) { + Batch batch = new Batch(); + batch.setBehaviors(new Behavior[batchModel.getBehaviors().size()]); + batch.setId(batchModel.getId()); + batch.setParentId(batchModel.getParentId()); + batch.setChildId(batchModel.getChildId()); + if (batchModel.getBehaviors() == null) { + return batch; + } + batch.setBehaviors(new Behavior[batchModel.getBehaviors().size()]); + for (int i = 0; i < batchModel.getBehaviors().size(); ++i) { + batch.getBehaviors()[i] = extractBehavior(batchModel.getBehaviors() + .get(i)); + } + return batch; + } + + private static void extractUsePlugins(RunScenarioModel runScenarioModel, + Scenario scenario) { + int i; + List usePluginModels = runScenarioModel.getUsePlugins(); + for (i = 0; i < runScenarioModel.getUsePlugins().size(); i++) { + UsePluginModel usePluginModel = usePluginModels.get(i); + UsePlugin usePlugin = extractUsePlugin(usePluginModel); + scenario.getUsePlugins()[i] = usePlugin; + } + } + + private static Behavior extractBehavior(BehaviorModel behaviorModel) { + Behavior behavior = BehaviorFactory.getBuisinessObject(behaviorModel); + behavior.setName(behaviorModel.getName()); + behavior.setUse(behaviorModel.getUse()); + behavior.setId(behaviorModel.getId()); + behavior.setParameters(new Parameter[behaviorModel.getParameters() + .size()]); + + int k = 0; + for (k = 0; k < behaviorModel.getParameters().size(); k++) { + ParameterModel parameterModel = behaviorModel.getParameters() + .get(k); + Parameter parameter = extractParameter(parameterModel); + behavior.getParameters()[k] = parameter; + } + return behavior; + } + + private static UsePlugin extractUsePlugin(UsePluginModel usePluginModel) { + UsePlugin usePlugin = new UsePlugin(); + usePlugin.setId(usePluginModel.getId()); + usePlugin.setName(usePluginModel.getName()); + usePlugin.setParameters(new Parameter[usePluginModel.getParameters() + .size()]); + int k = 0; + for (k = 0; k < usePluginModel.getParameters().size(); k++) { + ParameterModel parameterModel = usePluginModel.getParameters().get( + k); + Parameter parameter = extractParameter(parameterModel); + usePlugin.getParameters()[k] = parameter; + } + return usePlugin; + } + + private static Parameter extractParameter(ParameterModel parameterModel) { + Parameter parameter = new Parameter(); + parameter.setKey(parameterModel.getKey()); + parameter.setValue(parameterModel.getValue()); + return parameter; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/ScenarioContext.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/ScenarioContext.java new file mode 100644 index 00000000..f3454810 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/ScenarioContext.java @@ -0,0 +1,84 @@ +package org.bench4q.agent.scenario; + +import java.util.Date; +import java.util.UUID; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.ScenarioResultCollector; + +public class ScenarioContext { + private static final long keepAliveTime = 10; + private Date startDate; + private Date endDate; + private ThreadPoolExecutor executor; + private Scenario scenario; + private boolean finished; + private DataCollector dataStatistics; + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date saveStartDate) { + this.startDate = saveStartDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public ThreadPoolExecutor getExecutor() { + return executor; + } + + public void setExecutorService(ThreadPoolExecutor executor) { + this.executor = executor; + } + + public Scenario getScenario() { + return scenario; + } + + public void setScenario(Scenario scenario) { + this.scenario = scenario; + } + + public boolean isFinished() { + return finished; + } + + public void setFinished(boolean finished) { + this.finished = finished; + } + + public DataCollector getDataStatistics() { + return dataStatistics; + } + + private void setDataStatistics(DataCollector dataStatistics) { + this.dataStatistics = dataStatistics; + } + + public static ScenarioContext buildScenarioContext(UUID testId, + final Scenario scenario, int poolSize) { + ScenarioContext scenarioContext = new ScenarioContext(); + final SynchronousQueue workQueue = new SynchronousQueue(); + ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, + poolSize, keepAliveTime, TimeUnit.MINUTES, workQueue, + new DiscardPolicy()); + scenarioContext.setScenario(scenario); + scenarioContext.setStartDate(new Date(System.currentTimeMillis())); + scenarioContext.setExecutorService(executor); + scenarioContext.setDataStatistics(new ScenarioResultCollector(testId)); + return scenarioContext; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/ScenarioEngine.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/ScenarioEngine.java new file mode 100644 index 00000000..141b1e23 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/ScenarioEngine.java @@ -0,0 +1,92 @@ +package org.bench4q.agent.scenario; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.apache.log4j.Logger; +import org.bench4q.agent.parameterization.impl.InstanceControler; +import org.bench4q.agent.storage.StorageHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ScenarioEngine { + private Map runningTests; + private StorageHelper storageHelper; + private Logger logger; + + @SuppressWarnings("unused") + private Logger getLogger() { + return logger; + } + + private void setLogger(Logger logger) { + this.logger = logger; + } + + public ScenarioEngine() { + this.setRunningTests(new HashMap()); + this.setLogger(Logger.getLogger(ScenarioEngine.class)); + } + + public StorageHelper getStorageHelper() { + return storageHelper; + } + + @Autowired + public void setStorageHelper(StorageHelper storageHelper) { + this.storageHelper = storageHelper; + } + + public Map getRunningTests() { + return runningTests; + } + + private void setRunningTests(Map runningTests) { + this.runningTests = runningTests; + } + + public void submitScenario(UUID runId, final Scenario scenario, int poolSize) { + try { + final ScenarioContext scenarioContext = ScenarioContext + .buildScenarioContext(runId, scenario, poolSize); + this.getRunningTests().put(runId, scenarioContext); + + System.out.println(poolSize); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public boolean runWith(UUID runId) { + if (!this.getRunningTests().containsKey(runId)) { + return false; + } + final ScenarioContext context = this.getRunningTests().get(runId); + return runWith(context); + } + + private boolean runWith(final ScenarioContext scenarioContext) { + if (scenarioContext == null) { + logger.error("The context required is null"); + return false; + } + ExecutorService taskMaker = Executors.newSingleThreadExecutor(); + + taskMaker.execute(new Runnable() { + public void run() { + while (!scenarioContext.isFinished()) { + scenarioContext.getExecutor() + .execute( + new Worker(scenarioContext, + new InstanceControler())); + } + } + }); + return true; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/SessionContext.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/SessionContext.java new file mode 100644 index 00000000..ac9813bf --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/SessionContext.java @@ -0,0 +1,28 @@ +package org.bench4q.agent.scenario; + +import java.util.HashMap; +import java.util.Map; + +public class SessionContext { + Map variables; + + private Map getVariables() { + return variables; + } + + private void setVariables(Map variables) { + this.variables = variables; + } + + public SessionContext() { + this.setVariables(new HashMap()); + } + + public void addAVariable(String entryName, String entryValue) { + this.getVariables().put(entryName, entryValue); + } + + public String getVariable(String entryName) { + return this.getVariable(entryName); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/TestResult.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/TestResult.java new file mode 100644 index 00000000..6457ca30 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/TestResult.java @@ -0,0 +1,111 @@ +package org.bench4q.agent.scenario; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "testResult") +public class TestResult implements Serializable { + private static final long serialVersionUID = -370091935554266546L; + private UUID runId; + private int poolSize; + private int totalCount; + private Date startDate; + private long elapsedTime; + private int successCount; + private int failCount; + private int finishedCount; + private double averageResponseTime; + private List results; + + @XmlElement + public UUID getRunId() { + return runId; + } + + public void setRunId(UUID runId) { + this.runId = runId; + } + + @XmlElement + public int getPoolSize() { + return poolSize; + } + + public void setPoolSize(int poolSize) { + this.poolSize = poolSize; + } + + @XmlElement + public int getTotalCount() { + return totalCount; + } + + public void setTotalCount(int totalCount) { + this.totalCount = totalCount; + } + + @XmlElement + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public long getElapsedTime() { + return elapsedTime; + } + + public void setElapsedTime(long elapsedTime) { + this.elapsedTime = elapsedTime; + } + + public int getSuccessCount() { + return successCount; + } + + public void setSuccessCount(int successCount) { + this.successCount = successCount; + } + + public int getFailCount() { + return failCount; + } + + public void setFailCount(int failCount) { + this.failCount = failCount; + } + + public int getFinishedCount() { + return finishedCount; + } + + public void setFinishedCount(int finishedCount) { + this.finishedCount = finishedCount; + } + + public double getAverageResponseTime() { + return averageResponseTime; + } + + public void setAverageResponseTime(double averageResponseTime) { + this.averageResponseTime = averageResponseTime; + } + + @XmlElementWrapper(name = "results") + @XmlElement(name = "result") + public List getResults() { + return results; + } + + public void setResults(List results) { + this.results = results; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/TestResultItem.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/TestResultItem.java new file mode 100644 index 00000000..39481fa8 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/TestResultItem.java @@ -0,0 +1,93 @@ +package org.bench4q.agent.scenario; + +import java.io.Serializable; +import java.util.Date; +import java.util.UUID; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "testResultItem") +public class TestResultItem implements Serializable { + private static final long serialVersionUID = 3307951299814477213L; + private UUID id; + private String pluginId; + private String pluginName; + private String behaviorName; + private Date startDate; + private Date endDate; + private long responseTime; + private boolean success; + + @XmlElement + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + @XmlElement + public String getPluginId() { + return pluginId; + } + + public void setPluginId(String pluginId) { + this.pluginId = pluginId; + } + + @XmlElement + public String getPluginName() { + return pluginName; + } + + public void setPluginName(String pluginName) { + this.pluginName = pluginName; + } + + @XmlElement + public String getBehaviorName() { + return behaviorName; + } + + public void setBehaviorName(String behaviorName) { + this.behaviorName = behaviorName; + } + + @XmlElement + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + @XmlElement + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + @XmlElement + public long getResponseTime() { + return responseTime; + } + + public void setResponseTime(long responseTime) { + this.responseTime = responseTime; + } + + @XmlElement + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/UsePlugin.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/UsePlugin.java new file mode 100644 index 00000000..3e7379dd --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/UsePlugin.java @@ -0,0 +1,32 @@ +package org.bench4q.agent.scenario; + +public class UsePlugin { + private String id; + private String name; + private Parameter[] parameters; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Parameter[] getParameters() { + return parameters; + } + + public void setParameters(Parameter[] parameters) { + this.parameters = parameters; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Worker.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Worker.java new file mode 100644 index 00000000..587bcc04 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Worker.java @@ -0,0 +1,168 @@ +package org.bench4q.agent.scenario; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.helper.ApplicationContextHelper; +import org.bench4q.agent.parameterization.SessionObject; +import org.bench4q.agent.plugin.Plugin; +import org.bench4q.agent.plugin.PluginManager; +import org.bench4q.agent.plugin.result.HttpReturn; +import org.bench4q.agent.plugin.result.PluginReturn; +import org.bench4q.agent.scenario.behavior.Behavior; + +public class Worker implements Runnable { + private ScenarioContext scenarioContext; + private SessionObject sessionObject; + + private PluginManager pluginManager; + + private ScenarioContext getScenarioContext() { + return scenarioContext; + } + + private void setScenarioContext(ScenarioContext scenarioContext) { + this.scenarioContext = scenarioContext; + } + + private SessionObject getSessionObject() { + return sessionObject; + } + + private void setSessionObject(SessionObject sessionObject) { + this.sessionObject = sessionObject; + } + + private PluginManager getPluginManager() { + return pluginManager; + } + + private void setPluginManager(PluginManager pluginManager) { + this.pluginManager = pluginManager; + } + + public Worker(ScenarioContext scenarioContext, SessionObject sessionObject) { + this.setScenarioContext(scenarioContext); + this.setPluginManager(ApplicationContextHelper.getContext().getBean( + PluginManager.class)); + this.setSessionObject(sessionObject); + } + + public void run() { + doRunScenario(getScenarioContext()); + doCleanUp(); + } + + private void doCleanUp() { + this.sessionObject.doCleanUp(); + } + + public void doRunScenario(ScenarioContext context) { + Map plugins = new HashMap(); + preparePlugins(context.getScenario(), plugins); + for (int i = 0; i < context.getScenario().getPages().length; i++) { + Page page = context.getScenario().getPages()[i]; + context.getDataStatistics().add( + PageResult.buildPageResult( + i, + doRunBatchesInPage(plugins, page, + context.getDataStatistics()))); + } + + } + + private List doRunBatchesInPage( + Map plugins, Page page, DataCollector dataCollector) { + List results = new ArrayList(); + for (Batch batch : page.getBatches()) { + results.addAll(doRunBatch(plugins, batch, dataCollector)); + } + return results; + } + + private List doRunBatch(Map plugins, + Batch batch, DataCollector dataCollector) { + List results = new ArrayList(); + for (Behavior behavior : batch.getBehaviors()) { + // each execution should call this + behavior.distillParams(this.getSessionObject()); + Object plugin = plugins.get(behavior.getUse()); + Map behaviorParameters = prepareBehaviorParameters(behavior); + Date startDate = new Date(System.currentTimeMillis()); + PluginReturn pluginReturn = (PluginReturn) this.getPluginManager() + .doBehavior(plugin, behavior.getName(), behaviorParameters); + extractRunTimeParams(pluginReturn); + Date endDate = new Date(System.currentTimeMillis()); + if (!behavior.shouldBeCountResponseTime()) { + continue; + } + BehaviorResult behaviorResult = buildBehaviorResult(behavior, + plugin, startDate, pluginReturn, endDate); + pluginReturn = null; + dataCollector.add(behaviorResult); + results.add(behaviorResult); + } + return results; + } + + private void extractRunTimeParams(PluginReturn pluginReturn) { + this.getSessionObject().saveRuntimeParams( + pluginReturn.getRunTimeParams()); + } + + private BehaviorResult buildBehaviorResult(Behavior behavior, + Object plugin, Date startDate, PluginReturn pluginReturn, + Date endDate) { + BehaviorResult result = new BehaviorResult(); + result.setStartDate(startDate); + result.setEndDate(endDate); + result.setSuccess(pluginReturn.isSuccess()); + result.setResponseTime(endDate.getTime() - startDate.getTime()); + result.setBehaviorName(behavior.getName()); + result.setPluginId(behavior.getUse()); + result.setPluginName(plugin.getClass().getAnnotation(Plugin.class) + .value()); + result.setShouldBeCountResponseTime(behavior + .shouldBeCountResponseTime()); + if (pluginReturn instanceof HttpReturn) { + HttpReturn httpReturn = (HttpReturn) pluginReturn; + result.setBehaviorId(behavior.getId()); + for (Parameter parameter : behavior.getParameters()) { + if (parameter.getKey().equals("url")) { + result.setBehaviorUrl(parameter.getValue()); + } + } + result.setContentLength(httpReturn.getContentLength()); + result.setContentType(httpReturn.getContentType()); + result.setStatusCode(httpReturn.getStatusCode()); + } + return result; + } + + private Map prepareBehaviorParameters(Behavior behavior) { + Map behaviorParameters = new HashMap(); + for (Parameter parameter : behavior.getParameters()) { + behaviorParameters.put(parameter.getKey(), parameter.getValue()); + } + return behaviorParameters; + } + + private void preparePlugins(Scenario scenario, Map plugins) { + for (UsePlugin usePlugin : scenario.getUsePlugins()) { + String pluginId = usePlugin.getId(); + Class pluginClass = this.getPluginManager().getPlugins() + .get(usePlugin.getName()); + Map initParameters = new HashMap(); + for (Parameter parameter : usePlugin.getParameters()) { + initParameters.put(parameter.getKey(), parameter.getValue()); + } + Object plugin = this.getPluginManager().initializePlugin( + pluginClass, initParameters); + plugins.put(pluginId, plugin); + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/Behavior.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/Behavior.java new file mode 100644 index 00000000..80142d7a --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/Behavior.java @@ -0,0 +1,71 @@ +package org.bench4q.agent.scenario.behavior; + +import java.util.Map; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.BehaviorStatusCodeResult; +import org.bench4q.agent.parameterization.SessionObject; +import org.bench4q.agent.scenario.Parameter; + +public abstract class Behavior { + private int id; + private String use; + private String name; + private Parameter[] parameters; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getUse() { + return use; + } + + public void setUse(String use) { + this.use = use; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Parameter[] getParameters() { + return parameters; + } + + public void setParameters(Parameter[] parameters) { + this.parameters = parameters; + } + + public abstract boolean shouldBeCountResponseTime(); + + public abstract Map getBehaviorBriefResult( + DataCollector dataStatistics); + + public String getUrl() { + for (Parameter parameter : this.getParameters()) { + if (parameter.getKey().equals("url")) { + return parameter.getValue(); + } + } + return ""; + } + + public void distillParams(SessionObject session) { + for (Parameter parameter : this.getParameters()) { + String s = parameter.getValue(); + System.out.println("before Change :" + s); + String re = session.getParam(s); + System.out.println("after Change : " + re); + parameter.setValue(re); + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/BehaviorFactory.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/BehaviorFactory.java new file mode 100644 index 00000000..e5761868 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/BehaviorFactory.java @@ -0,0 +1,14 @@ +package org.bench4q.agent.scenario.behavior; + +import org.bench4q.share.models.agent.scriptrecord.BehaviorModel; + +public class BehaviorFactory { + public static Behavior getBuisinessObject(BehaviorModel modelInput) { + if (modelInput.getType().equalsIgnoreCase("TIMERBEHAVIOR")) { + return new TimerBehavior(); + } else if (modelInput.getType().equalsIgnoreCase("USERBEHAVIOR")) { + return new UserBehavior(); + } + return null; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/TimerBehavior.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/TimerBehavior.java new file mode 100644 index 00000000..c99d80aa --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/TimerBehavior.java @@ -0,0 +1,21 @@ +package org.bench4q.agent.scenario.behavior; + +import java.util.Map; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.BehaviorStatusCodeResult; + +public class TimerBehavior extends Behavior { + + @Override + public boolean shouldBeCountResponseTime() { + return false; + } + + @Override + public Map getBehaviorBriefResult( + DataCollector dataStatistics) { + return null; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/UserBehavior.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/UserBehavior.java new file mode 100644 index 00000000..6fe473d5 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/UserBehavior.java @@ -0,0 +1,20 @@ +package org.bench4q.agent.scenario.behavior; + +import java.util.Map; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.BehaviorStatusCodeResult; + +public class UserBehavior extends Behavior { + @Override + public boolean shouldBeCountResponseTime() { + return true; + } + + @Override + public Map getBehaviorBriefResult( + DataCollector dataStatistics) { + return dataStatistics.getBehaviorBriefStatistics(this.getId()); + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/util/ParameterParser.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/util/ParameterParser.java new file mode 100644 index 00000000..e8c81bf2 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/util/ParameterParser.java @@ -0,0 +1,122 @@ +package org.bench4q.agent.scenario.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.bench4q.agent.plugin.basic.http.ParameterConstant; + +/** + * + * @author coderfengyun + * + */ +public abstract class ParameterParser { + private static final String RadioGroup_SEPARATOR = ";"; + private static final String NFIELD_SEPARATOR = RadioGroup_SEPARATOR; + + static public List buildNField(String value) { + StringTokenizer st = new StringTokenizer(value, NFIELD_SEPARATOR, false); + List result = new ArrayList(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + result.add(token.trim()); + } + return result; + } + + static public String buildRadioGroup(String value) { + List realTokens = getRealTokens(RadioGroup_SEPARATOR, value, + false); + if (realTokens.size() == 0) { + return ""; + } else { + return unescape(realTokens.get(0)); + } + } + + static public List buildCheckBox(String value) { + return buildNField(value); + } + + static public String buildCombo(String value) { + return buildRadioGroup(value); + } + + static public Table buildTable(String value, List columnLables) { + return Table.buildTable(value, columnLables); + } + + /** + * Get the number of escape character in the end of the string + * + * @param value + * The string to be analyzed + * @return 0 if no escape character was found, else the number + */ + private static int getNumberOfEscapeCharacter(String value) { + int result = 0; + if (value.length() > 0) { + int last = value.lastIndexOf(ParameterConstant.escape); + if (last == value.length() - 1) { + result = 1 + getNumberOfEscapeCharacter(value + .substring(0, last)); + } + } + return result; + } + + /** + * Split the string value with the separator, and check if there is no + * escape character before the separator + * + * @param separator + * The separator + * @param value + * The string value to be split + * @return The vector containing each token + */ + static List getRealTokens(String separator, String value, + boolean toUnescapeSeparator) { + List result = new ArrayList(); + for (String entry : value.split(separator)) { + if (getNumberOfEscapeCharacter(entry) % 2 != 0) { + if (toUnescapeSeparator) { + entry = entry.substring(0, entry.length() - 1) + + unescape(separator); + } else { + entry = entry.substring(0, entry.length() - 1) + separator; + } + } + result.add(entry); + } + return result; + } + + /** + * Replaces every escape sequences by the corresponding original character + * + * @param value + * the string where some characters are escaped by '\' character + * @return the unescaped string + */ + static String unescape(String value) { + StringBuilder result = new StringBuilder(); + char c; + boolean escape = false; // escape sequence + for (int i = 0; i < value.length(); ++i) { + c = value.charAt(i); + if (escape) { + result.append(c); + escape = false; + } else { + if (c == ParameterConstant.escape.charAt(0)) { + escape = true; + } else { + result.append(c); + } + } + } + return result.toString(); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/util/Table.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/util/Table.java new file mode 100644 index 00000000..866287b3 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/util/Table.java @@ -0,0 +1,115 @@ +package org.bench4q.agent.scenario.util; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.bench4q.agent.plugin.basic.http.ParameterConstant; + +public class Table { + public static final String ROW_SEPARATOR = "|;"; + public static final String COLUMN_SEPARATOR = "|"; + public static final String ROW_SEPARATOR_TAIL = ";"; + + public static final String ESCAPE_ROW_SEPARATOR = ParameterConstant.escape + + ROW_SEPARATOR; + public static final String ESCAPE_COLUMN_SEPARATOR = ParameterConstant.escape + + COLUMN_SEPARATOR; + private List> realContent; + private List columnLables; + + public List> getRealContent() { + return realContent; + } + + private void setRealContent(List> realContent) { + this.realContent = realContent; + } + + private List getColumnLables() { + return columnLables; + } + + private void setColumnLables(List columnLables) { + this.columnLables = columnLables; + } + + private Table() { + this.setColumnLables(new LinkedList()); + } + + static Table buildTable(String value, List columnLablesInSequence) { + Table result = new Table(); + result.setRealContent(buildTableContent(value)); + result.setColumnLables(columnLablesInSequence); + return result; + } + + /** + * This method analyzes the value to be set in the table, and remove all + * escape characters + * + * @param value + * The value containing the serialization of all values of the + * table + * @return The vector containing all the entries, each entries is in a + * vector, which contains the string values + */ + private static List> buildTableContent(String value) { + List tempEntries = ParameterParser.getRealTokens( + Table.ESCAPE_ROW_SEPARATOR, value, false); + List> allValues = new ArrayList>(); + for (int i = 0; i < tempEntries.size(); i++) { + String tempEntry = tempEntries.get(i); + List values = ParameterParser.getRealTokens( + Table.ESCAPE_COLUMN_SEPARATOR, tempEntry, true); + arrangeTableWithRowSeparatorTail(values); + allValues.add(values); + } + // now analyze all values, and get the '=' separator + return extractValueFromWellFormedTable(allValues); + } + + private static List> extractValueFromWellFormedTable( + List> allValues) { + List> result = new LinkedList>(); + for (int i = 0; i < allValues.size(); i++) { + List resultValues = new ArrayList(); + List tempValues = allValues.get(i); + for (int j = 0; j < tempValues.size(); j++) { + String v = tempValues.get(j); + List temp = ParameterParser + .getRealTokens("=", v, false); + String res; + if (temp.size() <= 1) { + continue; + } + res = temp.get(1); + resultValues.add(res); + } + result.add(resultValues); + } + return result; + } + + /** + * This method check if the table_separator after escape is split by the + * table_entry_separator + * + * @param values + */ + private static void arrangeTableWithRowSeparatorTail(List values) { + for (int i = 0; i < values.size(); i++) { + + String currentToken = values.get(i); + if (currentToken.equals(Table.ROW_SEPARATOR_TAIL) && i > 0) { + values.set(i - 1, values.get(i - 1) + Table.ROW_SEPARATOR_TAIL); + } + } + + } + + public int getColumnCount() { + return this.getColumnLables().size(); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/share/DealWithLog.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/share/DealWithLog.java new file mode 100644 index 00000000..3c18c981 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/share/DealWithLog.java @@ -0,0 +1,13 @@ +package org.bench4q.agent.share; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +public class DealWithLog { + public static ByteArrayOutputStream getExceptionStackTrace(Exception e) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(outputStream); + e.printStackTrace(printStream); + return outputStream; + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/Buffer.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/Buffer.java new file mode 100644 index 00000000..a40de8bd --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/Buffer.java @@ -0,0 +1,57 @@ +package org.bench4q.agent.storage; + +public class Buffer { + private byte[] content; + private int currentPos; + private int totalSize; + + public byte[] getContent() { + return content; + } + + public void setContent(byte[] content) { + this.content = content; + } + + public int getCurrentPos() { + return currentPos; + } + + public void setCurrentPos(int currentPos) { + this.currentPos = currentPos; + } + + public int getTotalSize() { + return totalSize; + } + + public void setTotalSize(int totalSize) { + this.totalSize = totalSize; + } + + public static Buffer createBuffer(int totalSize) { + Buffer buffer = new Buffer(); + buffer.setContent(new byte[totalSize]); + buffer.setCurrentPos(0); + buffer.setTotalSize(totalSize); + return buffer; + } + + public int getRemainSize() { + return this.totalSize - this.currentPos; + } + + public void reset() { + this.setCurrentPos(0); + } + + public void setFull() { + this.setCurrentPos(this.getTotalSize()); + } + + void writeToCurrentBuffer(int size, byte[] cache) { + System.arraycopy(cache, 0, this.getContent(), this.getCurrentPos(), + size); + this.setCurrentPos(this.getCurrentPos() + size); + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/DoubleBufferStorage.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/DoubleBufferStorage.java new file mode 100644 index 00000000..f92f050e --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/DoubleBufferStorage.java @@ -0,0 +1,157 @@ +package org.bench4q.agent.storage; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FilenameFilter; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.bench4q.share.models.agent.CleanTestResultModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class DoubleBufferStorage { + private static final int THRESHOLD = 1024; + private static Charset charset = Charset.forName("utf-8"); + private static int BUFFER_SIZE = 48 * 1024; + private List bufferList; + private int currentBufferIndex; + private LocalStorage localStorage; + public CleanTestResultModel forTest = new CleanTestResultModel(); + + private int getCurrentBufferIndex() { + return currentBufferIndex; + } + + private void setCurrentBufferIndex(int currentBuffer) { + this.currentBufferIndex = currentBuffer; + } + + private List getBufferList() { + return bufferList; + } + + private void setBufferList(List bufferList) { + this.bufferList = bufferList; + } + + private LocalStorage getLocalStorage() { + return localStorage; + } + + @Autowired + private void setLocalStorage(LocalStorage localStorage) { + this.localStorage = localStorage; + } + + public DoubleBufferStorage() { + this.setBufferList(new ArrayList()); + this.getBufferList().add(Buffer.createBuffer(BUFFER_SIZE)); + this.getBufferList().add(Buffer.createBuffer(BUFFER_SIZE)); + this.setCurrentBufferIndex(0); + } + + public String readFiles(String pathPrefix) { + int pos = pathPrefix.lastIndexOf(System.getProperty("file.separator")); + String dirPath = pathPrefix.substring(0, pos); + final String prefix = pathPrefix.substring(pos + 1); + String result = new String(); + + File dirFile = new File(dirPath); + if (!dirFile.exists()) { + return ""; + } + File[] files = dirFile.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.contains(prefix); + } + }); + for (File file : files) { + if (!file.exists()) { + continue; + } + result += this.getLocalStorage().readFile(file.getAbsolutePath()); + } + return result; + } + + public boolean writeFile(String content, String path) { + ByteArrayInputStream inputStream = new ByteArrayInputStream( + content.getBytes(charset)); + int size = -1; + byte[] cache = new byte[THRESHOLD]; + while ((size = inputStream.read(cache, 0, THRESHOLD)) != -1) { + if (isCurrentBufferFull(size)) { + doSave(calculateSavePath(path)); + changeToTheMaxRemainBuffer(); + } + this.getCurrentBuffer().writeToCurrentBuffer(size, cache); + } + return true; + } + + private boolean isCurrentBufferFull(int size) { + return getCurrentBuffer().getRemainSize() <= THRESHOLD + size; + } + + public String calculateSavePath(String path, int index) { + return path.substring(0, path.lastIndexOf(".")) + "_" + index + ".xml"; + } + + private String calculateSavePath(String path) { + return calculateSavePath(path, this.getCurrentBufferIndex()); + } + + private void doSave(final String path) { + final Buffer bufferUnderSave = this.getCurrentBuffer(); + final String writeContent = this.getMeaningfulContent(); + Runnable runnable = new Runnable() { + public void run() { + getLocalStorage().writeFile(writeContent, path); + bufferUnderSave.reset(); + forTest.setSuccess(true); + } + }; + ExecutorService service = Executors.newFixedThreadPool(1); + service.execute(runnable); + service.shutdown(); + + } + + private String getMeaningfulContent() { + byte[] meaningfulContent = new byte[getCurrentBuffer().getCurrentPos()]; + System.arraycopy(getCurrentBuffer().getContent(), 0, meaningfulContent, + 0, getCurrentBuffer().getCurrentPos()); + return new String(meaningfulContent); + } + + private void changeToTheMaxRemainBuffer() { + int maxRemainSize = 2 * THRESHOLD; + int maxRemainSizeBufferIndex = -1; + for (int i = 0; i < this.getBufferList().size(); ++i) { + System.out.println(i + " remain : " + + this.getBufferList().get(i).getRemainSize()); + if (this.getBufferList().get(i).getRemainSize() > maxRemainSize) { + maxRemainSize = this.getBufferList().get(i).getRemainSize(); + maxRemainSizeBufferIndex = i; + } + } + if (maxRemainSizeBufferIndex == -1) { + this.getBufferList().add(Buffer.createBuffer(BUFFER_SIZE)); + maxRemainSizeBufferIndex = this.getBufferList().size() - 1; + } + this.setCurrentBufferIndex(maxRemainSizeBufferIndex); + } + + private Buffer getCurrentBuffer() { + return this.getBufferList().get(this.getCurrentBufferIndex()); + } + + public void flush() { + + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/HdfsStorage.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/HdfsStorage.java new file mode 100644 index 00000000..9d9e0694 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/HdfsStorage.java @@ -0,0 +1,140 @@ +package org.bench4q.agent.storage; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FSDataInputStream; +import org.apache.hadoop.fs.FSDataOutputStream; +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.IOUtils; +import org.springframework.stereotype.Component; + +@Component +public class HdfsStorage implements Storage { + private FileSystem getFileSystem() throws IOException { + Configuration conf = new Configuration(); + conf.set("mapred.jop.tracker", "hdfs://133.133.12.21:9001"); + conf.set("fs.default.name", "hdfs://133.133.12.21:9000"); + return FileSystem.get(conf); + } + + public boolean uploadFile(String localPath, String remotePath) { + try { + FileSystem fs = this.getFileSystem(); + fs.copyFromLocalFile(new Path(localPath), new Path(remotePath)); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean writeFile(String content, String remotePath) { + try { + InputStream in = new ByteArrayInputStream(content.getBytes()); + FileSystem fs = this.getFileSystem(); + OutputStream out = fs.create(new Path(remotePath)); + IOUtils.copyBytes(in, out, 4096, true); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean downloadFile(String localPath, String remotePath) { + try { + FileSystem fs = this.getFileSystem(); + fs.copyToLocalFile(new Path(remotePath), new Path(localPath)); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public String readFile(String remotePath) { + try { + FileSystem fs = this.getFileSystem(); + FSDataInputStream hdfsInStream = fs.open(new Path(remotePath)); + OutputStream out = new ByteArrayOutputStream(); + byte[] ioBuffer = new byte[1024]; + int readLen = hdfsInStream.read(ioBuffer); + while (-1 != readLen) { + out.write(ioBuffer, 0, readLen); + readLen = hdfsInStream.read(ioBuffer); + } + out.close(); + String ret = out.toString(); + hdfsInStream.close(); + return ret; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public boolean appendFile(String content, String remotePath) { + try { + FileSystem fs = this.getFileSystem(); + FSDataOutputStream out = fs.append(new Path(remotePath)); + int readLen = content.getBytes().length; + while (-1 != readLen) { + out.write(content.getBytes(), 0, readLen); + } + out.close(); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean deleteFile(String remotePath) { + try { + FileSystem fs = this.getFileSystem(); + return fs.delete(new Path(remotePath), false); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean deleteDirectory(String remotePath) { + try { + FileSystem fs = this.getFileSystem(); + return fs.delete(new Path(remotePath), true); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean renameFile(String fromPath, String toPath) { + try { + FileSystem fs = this.getFileSystem(); + return fs.rename(new Path(fromPath), new Path(toPath)); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public FileStatus[] listFile(String remotePath) { + try { + FileSystem fs = this.getFileSystem(); + FileStatus[] fileList = fs.listStatus(new Path(remotePath)); + return fileList; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/LocalStorage.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/LocalStorage.java new file mode 100644 index 00000000..6eb1b2da --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/LocalStorage.java @@ -0,0 +1,50 @@ +package org.bench4q.agent.storage; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; + +import org.springframework.stereotype.Component; + +@Component +public class LocalStorage implements Storage { + + public String readFile(String path) { + try { + InputStreamReader inputStreamReader = new InputStreamReader( + new FileInputStream(new File(path)), "UTF-8"); + StringBuffer ret = new StringBuffer(); + int toRead; + while ((toRead = inputStreamReader.read()) != -1) { + ret.append((char) toRead); + } + inputStreamReader.close(); + return ret.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public boolean writeFile(String content, String path) { + try { + String dirPath = path.substring(0, + path.lastIndexOf(System.getProperty("file.separator"))); + File file = new File(dirPath); + if (!file.exists()) { + file.mkdirs(); + } + OutputStreamWriter outputStreamWriter = new OutputStreamWriter( + new FileOutputStream(new File(path), true), "UTF-8"); + outputStreamWriter.write(content); + outputStreamWriter.flush(); + outputStreamWriter.close(); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/MooseStorage.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/MooseStorage.java new file mode 100644 index 00000000..ec8eabfb --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/MooseStorage.java @@ -0,0 +1,17 @@ +package org.bench4q.agent.storage; + +import org.springframework.stereotype.Component; + +@Component +public class MooseStorage implements Storage { + + public String readFile(String path) { + + return null; + } + + public boolean writeFile(String content, String path) { + return false; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/Storage.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/Storage.java new file mode 100644 index 00000000..6dbbe36d --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/Storage.java @@ -0,0 +1,7 @@ +package org.bench4q.agent.storage; + +public interface Storage { + public String readFile(String path); + + public boolean writeFile(String content, String path); +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/StorageHelper.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/StorageHelper.java new file mode 100644 index 00000000..7a49f28c --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/storage/StorageHelper.java @@ -0,0 +1,39 @@ +package org.bench4q.agent.storage; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class StorageHelper { + private HdfsStorage hdfsStorage; + private LocalStorage localStorage; + private MooseStorage mooseStorage; + + public HdfsStorage getHdfsStorage() { + return hdfsStorage; + } + + @Autowired + public void setHdfsStorage(HdfsStorage hdfsStorage) { + this.hdfsStorage = hdfsStorage; + } + + public LocalStorage getLocalStorage() { + return localStorage; + } + + @Autowired + public void setLocalStorage(LocalStorage localStorage) { + this.localStorage = localStorage; + } + + public MooseStorage getMooseStorage() { + return mooseStorage; + } + + @Autowired + public void setMooseStorage(MooseStorage mooseStorage) { + this.mooseStorage = mooseStorage; + } + +} diff --git a/Bench4Q-Agent/src/main/resources/log4j.properties b/Bench4Q-Agent/src/main/resources/log4j.properties new file mode 100644 index 00000000..0fa2c1c5 --- /dev/null +++ b/Bench4Q-Agent/src/main/resources/log4j.properties @@ -0,0 +1,31 @@ +log4j.rootLogger = INFO,WARN,ERROR,FALTAL,D + +log4j.appender.WARN = org.apache.log4j.DailyRollingFileAppender +log4j.appender.WARN.File = logs/log.log +log4j.appender.WARN.Append = true +log4j.appender.WARN.Threshold = WARN +log4j.appender.WARN.layout = org.apache.log4j.PatternLayout +log4j.appender.WARN.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n + +log4j.appender.ERROR = org.apache.log4j.DailyRollingFileAppender +log4j.appender.ERROR.File = logs/log.log +log4j.appender.ERROR.Append = true +log4j.appender.ERROR.Threshold = ERROR +log4j.appender.ERROR.layout = org.apache.log4j.PatternLayout +log4j.appender.ERROR.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n + +log4j.appender.FALTAL = org.apache.log4j.DailyRollingFileAppender +log4j.appender.FALTAL.File = logs/log.log +log4j.appender.FALTAL.Append = true +log4j.appender.FALTAL.Threshold = ERROR +log4j.appender.FALTAL.layout = org.apache.log4j.PatternLayout +log4j.appender.FALTAL.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n + + +log4j.appender.D = org.apache.log4j.DailyRollingFileAppender +log4j.appender.D.File = logs/log.log +log4j.appender.D.Append = true +log4j.appender.D.Threshold = INFO +log4j.appender.D.layout = org.apache.log4j.PatternLayout +log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n + diff --git a/Bench4Q-Agent/src/main/resources/org/bench4q/agent/config/application-context.xml b/Bench4Q-Agent/src/main/resources/org/bench4q/agent/config/application-context.xml new file mode 100644 index 00000000..48c14bb0 --- /dev/null +++ b/Bench4Q-Agent/src/main/resources/org/bench4q/agent/config/application-context.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/ExtractScenarioTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/ExtractScenarioTest.java new file mode 100644 index 00000000..8912eea5 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/ExtractScenarioTest.java @@ -0,0 +1,27 @@ +package org.bench4q.agent.test; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import javax.xml.bind.JAXBException; + +import org.apache.commons.io.FileUtils; +import org.bench4q.agent.scenario.Scenario; +import org.bench4q.share.helper.MarshalHelper; +import org.bench4q.share.models.agent.RunScenarioModel; +import org.junit.Test; + +public class ExtractScenarioTest { + + @Test + public void test() throws JAXBException, IOException { + RunScenarioModel runScenarioModel = (RunScenarioModel) MarshalHelper + .unmarshal(RunScenarioModel.class, FileUtils + .readFileToString(new File("Scripts/goodForPage.xml"))); + Scenario scenario = Scenario.scenarioBuilder(runScenarioModel); + + assertTrue(scenario.getPages().length > 0); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/HomeControllerTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/HomeControllerTest.java new file mode 100644 index 00000000..6902b437 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/HomeControllerTest.java @@ -0,0 +1,5 @@ +package org.bench4q.agent.test; + +public class HomeControllerTest { + +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/MainTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/MainTest.java new file mode 100644 index 00000000..70602654 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/MainTest.java @@ -0,0 +1,37 @@ +package org.bench4q.agent.test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; + +import org.bench4q.agent.Main; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class MainTest { + public MainTest() { + Main.init(); + } + + @Test + public void initTest() { + Main.init(); + assertTrue(new File("configure").exists()); + } + + @Test + public void getPropertiesTest() throws IOException { + FileInputStream inputStream = new FileInputStream(new File("configure" + + System.getProperty("file.separator") + + "agent-config.properties")); + Properties properties = new Properties(); + properties.load(inputStream); + assertEquals(6565, + Integer.parseInt((String) properties.get("servePort"))); + assertEquals(false, Boolean.parseBoolean((String) properties + .get("isToSaveDetailResult"))); + } + +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/PluginControllerTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/PluginControllerTest.java new file mode 100644 index 00000000..ca35983c --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/PluginControllerTest.java @@ -0,0 +1,5 @@ +package org.bench4q.agent.test; + +public class PluginControllerTest { + +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/TestWithScriptFile.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/TestWithScriptFile.java new file mode 100644 index 00000000..d9a83b3a --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/TestWithScriptFile.java @@ -0,0 +1,243 @@ +package org.bench4q.agent.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.*; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.io.FileUtils; +import org.bench4q.agent.parameterization.ParameterFileCollector; +import org.bench4q.share.communication.HttpRequester; +import org.bench4q.share.communication.HttpRequester.HttpResponse; +import org.bench4q.share.helper.MarshalHelper; +import org.bench4q.share.helper.TestHelper; +import org.bench4q.share.models.agent.BehaviorBriefModel; +import org.bench4q.share.models.agent.RunScenarioModel; +import org.bench4q.share.models.agent.RunScenarioResultModel; +import org.bench4q.share.models.agent.statistics.AgentBriefStatusModel; +import org.bench4q.share.models.agent.statistics.AgentBehaviorsBriefModel; +import org.bench4q.share.models.agent.statistics.AgentPageBriefModel; +import org.junit.Test; + +public class TestWithScriptFile { + private HttpRequester httpRequester; + private String url = "http://localhost:6565/test"; + private String filePath; + private UUID testId; + private static int load = 10; + + private String getFilePath() { + return filePath; + } + + private void setFilePath(String filePath) { + this.filePath = filePath; + } + + private HttpRequester getHttpRequester() { + return httpRequester; + } + + private void setHttpRequester(HttpRequester httpRequester) { + this.httpRequester = httpRequester; + } + + private UUID getTestId() { + return testId; + } + + private void setTestId(UUID testId) { + this.testId = testId; + } + + public TestWithScriptFile() { + this.setFilePath("Scripts" + System.getProperty("file.separator") + + "forGoodRecord.xml"); + this.setHttpRequester(new HttpRequester()); + } + + private void startTest() throws JAXBException { + try { + RunScenarioModel runScenarioModel = getScenarioModel(); + if (runScenarioModel == null) { + System.out.println("can't execute an invalid script"); + return; + } + assertTrue(runScenarioModel.getPages().size() > 0); + assertTrue(runScenarioModel.getPages().get(0).getBatches().get(0) + .getBehaviors().size() > 0); + + HttpResponse httpResponse = this.getHttpRequester().sendPostXml( + this.url + "/runWithoutParams", + marshalRunScenarioModel(runScenarioModel), null); + RunScenarioResultModel resultModel = (RunScenarioResultModel) MarshalHelper + .unmarshal(RunScenarioResultModel.class, + httpResponse.getContent()); + this.setTestId(resultModel.getRunId()); + } catch (IOException e) { + System.out.println("IO exception!"); + } + } + + private RunScenarioModel getScenarioModel() throws IOException { + String scriptContent; + File file = new File(this.getFilePath()); + if (!file.exists()) { + System.out.println("this script not exists!"); + return null; + } + scriptContent = FileUtils.readFileToString(file); + RunScenarioModel runScenarioModel = extractRunScenarioModel(scriptContent); + runScenarioModel.setPoolSize(load); + return runScenarioModel; + } + + private RunScenarioModel extractRunScenarioModel(String scriptContent) { + try { + Unmarshaller unmarshaller = JAXBContext.newInstance( + RunScenarioModel.class).createUnmarshaller(); + return (RunScenarioModel) unmarshaller + .unmarshal(new ByteArrayInputStream(scriptContent + .getBytes())); + } catch (JAXBException e) { + System.out.println("model unmarshal has an exception!"); + e.printStackTrace(); + return null; + } + + } + + private String marshalRunScenarioModel(RunScenarioModel model) + throws JAXBException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + JAXBContext.newInstance(RunScenarioModel.class).createMarshaller() + .marshal(model, outputStream); + return outputStream.toString(); + } + + private void stopTest() throws IOException { + System.out.println("Enter stopTest!"); + this.getHttpRequester().sendGet( + this.url + "/stop/" + this.getTestId().toString(), null, null); + } + + private void scenarioBrief() throws IOException, JAXBException { + System.out.println("Enter brief!"); + HttpResponse httpResponse = this.getHttpRequester().sendGet( + this.url + "/brief/" + this.getTestId().toString(), null, null); + System.out.println(httpResponse.getContent()); + AgentBriefStatusModel briefModel = (AgentBriefStatusModel) MarshalHelper + .unmarshal(AgentBriefStatusModel.class, + httpResponse.getContent()); + assertTrue(briefModel.getTimeFrame() > 0); + } + + private void behaviorsBrief() throws IOException, JAXBException { + System.out.println("Enter behaviorsBrief!"); + HttpResponse httpResponse = this.getHttpRequester().sendGet( + this.url + "/behaviorsBrief/" + this.getTestId().toString(), + null, null); + System.out.println(httpResponse.getContent()); + AgentBehaviorsBriefModel behaviorsBriefModel = (AgentBehaviorsBriefModel) MarshalHelper + .unmarshal(AgentBehaviorsBriefModel.class, + httpResponse.getContent()); + assertTrue(behaviorsBriefModel.getBehaviorBriefModels().size() > 0); + } + + private void behaviorBrief() throws IOException, JAXBException { + System.out.println("Enter behaviorBrief!"); + HttpResponse httpResponse = this.getHttpRequester().sendGet( + this.url + "/brief/" + this.getTestId().toString() + "/0", + null, null); + BehaviorBriefModel behaviorBriefModel = (BehaviorBriefModel) MarshalHelper + .unmarshal(BehaviorBriefModel.class, httpResponse.getContent()); + assertTrue(behaviorBriefModel.getDetailStatusCodeResultModels().size() > 0); + } + + @Test + public void integrateTest() throws JAXBException, InterruptedException, + IOException { + try { + this.startTest(); + Thread.sleep(5000); + this.scenarioBrief(); + Thread.sleep(5000); + this.behaviorsBrief(); + Thread.sleep(5000); + this.behaviorBrief(); + Thread.sleep(5000); + this.pageBrief(0); + } catch (Exception e) { + e.printStackTrace(); + } finally { + this.stopTest(); + } + + } + + @Test + public void testSubmitParamsAndRun() throws Exception { + List files = new ArrayList(); + files.add(new File("Scripts" + System.getProperty("file.separator") + + "forGoodRecord.xml")); + files.add(new File("Scripts" + System.getProperty("file.separator") + + "testJD.xml")); + HttpResponse httpResponse = this.getHttpRequester().postFiles( + url + "/submitScenarioWithParams", "files[]", files, + "scenarioModel", new LinkedList() { + private static final long serialVersionUID = 1L; + { + add(MarshalHelper.tryMarshal(getScenarioModel())); + } + }); + assertNotNull(httpResponse); + assertNotNull(httpResponse.getContent()); + assertEquals(200, httpResponse.getCode()); + RunScenarioResultModel resultModel = (RunScenarioResultModel) MarshalHelper + .tryUnmarshal(RunScenarioResultModel.class, + httpResponse.getContent()); + String dirPath = (String) TestHelper.invokePrivate( + new ParameterFileCollector(), "guardDirExists", + new Class[] { UUID.class }, + new Object[] { resultModel.getRunId() }); + File file = new File(dirPath); + assertTrue(file.exists()); + assertEquals(2, file.listFiles().length); + System.out.println(httpResponse.getContent()); + + httpResponse = this.getHttpRequester().sendPost( + this.url + "/runWithParams/" + + resultModel.getRunId().toString(), null, null); + assertNotNull(httpResponse); + System.out.println(httpResponse.getContent()); + } + + private void pageBrief(int i) throws IOException, JAXBException { + try { + HttpResponse httpResponse = this.getHttpRequester().sendGet( + url + "/pageBrief/" + this.getTestId() + "/" + i, null, + null); + if (httpResponse == null || httpResponse.getContent().isEmpty()) { + fail(); + } + System.out.println(httpResponse); + AgentPageBriefModel pageBriefModel = (AgentPageBriefModel) MarshalHelper + .unmarshal(AgentPageBriefModel.class, + httpResponse.getContent()); + assertTrue(pageBriefModel.getCountFromBegin() > 0); + } catch (Exception e) { + this.stopTest(); + } + + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/DetailStatisticsTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/DetailStatisticsTest.java new file mode 100644 index 00000000..1df3257a --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/DetailStatisticsTest.java @@ -0,0 +1,139 @@ +package org.bench4q.agent.test.datastatistics; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.ScenarioResultCollector; +import org.bench4q.agent.datacollector.impl.BehaviorStatusCodeResult; +import org.bench4q.agent.scenario.BehaviorResult; +import org.bench4q.agent.storage.StorageHelper; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class DetailStatisticsTest { + private DataCollector detailStatistics; + + private DataCollector getDetailStatistics() { + return detailStatistics; + } + + private void setDetailStatistics(DataCollector detailStatistics) { + this.detailStatistics = detailStatistics; + } + + public DetailStatisticsTest() { + init(); + } + + private void init() { + @SuppressWarnings("resource") + ApplicationContext context = new ClassPathXmlApplicationContext( + "classpath*:/org/bench4q/agent/config/application-context.xml"); + ScenarioResultCollector agentResultDataCollector = new ScenarioResultCollector( + UUID.randomUUID()); + agentResultDataCollector.setStorageHelper((StorageHelper) context + .getBean(StorageHelper.class)); + this.setDetailStatistics(agentResultDataCollector); + } + + @Test + public void addZeroTest() { + for (BehaviorResult behaviorResult : ScenarioStatisticsTest + .makeBehaviorList(0)) { + this.getDetailStatistics().add(behaviorResult); + } + + Object object = this.detailStatistics.getBehaviorBriefStatistics(0); + assertEquals(null, object); + } + + @Test + public void addOneDetailTest() { + for (BehaviorResult behaviorResult : ScenarioStatisticsTest + .makeBehaviorList(1)) { + this.getDetailStatistics().add(behaviorResult); + } + Map map = this.detailStatistics + .getBehaviorBriefStatistics(1); + + BehaviorStatusCodeResult actualResult = map.get(200); + assertTrue(actualResult.equals(makeExpectedResultForOne())); + } + + private BehaviorStatusCodeResult makeExpectedResultForOne() { + BehaviorStatusCodeResult ret = new BehaviorStatusCodeResult(""); + ret.contentLength = 20; + ret.count = 1; + ret.maxResponseTime = 200; + ret.minResponseTime = 200; + ret.totalResponseTimeThisTime = 200; + return ret; + } + + @Test + public void addTwoDetailTest() { + for (BehaviorResult behaviorResult : ScenarioStatisticsTest + .makeBehaviorList(2)) { + this.getDetailStatistics().add(behaviorResult); + } + Map map = this.detailStatistics + .getBehaviorBriefStatistics(1); + assertTrue(mapEquals(map, makeExpectedMapForTwo())); + } + + private Map makeExpectedMapForTwo() { + Map ret = new HashMap(); + ret.put(new Integer(200), buildCodeResult(20, 1, 200, 200, 200)); + ret.put(new Integer(400), buildCodeResult(0, 1, 0, 0, 0)); + return ret; + } + + private BehaviorStatusCodeResult buildCodeResult(long contentLength, + long count, long maxResponseTime, long minResponseTime, + long totalResponseTimeThisTime) { + BehaviorStatusCodeResult ret = new BehaviorStatusCodeResult(""); + ret.contentLength = contentLength; + ret.count = count; + ret.maxResponseTime = maxResponseTime; + ret.minResponseTime = minResponseTime; + ret.totalResponseTimeThisTime = totalResponseTimeThisTime; + return ret; + } + + private boolean mapEquals(Map mapActual, + Map mapExpected) { + boolean equal = true; + if (mapActual.size() != mapExpected.size()) { + return false; + } + for (int i : mapActual.keySet()) { + if (!mapActual.get(i).equals(mapExpected.get(i))) { + equal = false; + } + } + return equal; + } + + @Test + public void addThreeTest() { + for (BehaviorResult behaviorResult : ScenarioStatisticsTest + .makeBehaviorList(3)) { + this.getDetailStatistics().add(behaviorResult); + } + Map mapActual = this + .getDetailStatistics().getBehaviorBriefStatistics(1); + assertTrue(mapEquals(mapActual, makeExpectedMapForThree())); + } + + private Map makeExpectedMapForThree() { + Map retMap = new HashMap(); + retMap.put(200, buildCodeResult(40, 2, 220, 200, 420)); + retMap.put(400, buildCodeResult(0, 1, 0, 0, 0)); + return retMap; + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/PageResultStatisticsTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/PageResultStatisticsTest.java new file mode 100644 index 00000000..a6b4dad8 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/PageResultStatisticsTest.java @@ -0,0 +1,133 @@ +package org.bench4q.agent.test.datastatistics; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.PageResultCollector; +import org.bench4q.agent.scenario.PageResult; +import org.bench4q.share.models.agent.statistics.AgentPageBriefModel; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-storage-context.xml", + "classpath*:/org/bench4q/agent/config/application-context.xml" }) +public class PageResultStatisticsTest { + private DataCollector dataCollector; + + private DataCollector getDataCollector() { + return dataCollector; + } + + private void setDataCollector(DataCollector dataCollector) { + this.dataCollector = dataCollector; + } + + @SuppressWarnings("resource") + public PageResultStatisticsTest() { + new ClassPathXmlApplicationContext( + "classpath*:/org/bench4q/agent/config/application-context.xml"); + this.setDataCollector(new PageResultCollector()); + } + + @Test + public void pageResultTest() { + PageResult pageResult = PageResult.buildPageResult(2, + ScenarioStatisticsTest.makeBehaviorList(1)); + assertEquals(2, pageResult.getPageId()); + assertEquals(200, pageResult.getExecuteRange()); + assertTrue(pageResult.getPageStartTime() > 0); + } + + @Test + public void pageResultWithTwoBehaviorTest() { + PageResult pageResult = PageResult.buildPageResult(2, + ScenarioStatisticsTest.makeBehaviorList(2)); + assertEquals(2, pageResult.getPageId()); + assertEquals(220, pageResult.getExecuteRange()); + assertEquals(200, pageResult.getPageStartTime()); + assertEquals(420, pageResult.getPageEndTime()); + } + + @Test + public void testNull() { + this.getDataCollector().add((PageResult) null); + assertNotNull(dataCollector.getPageBriefStatistics(0)); + } + + @Test + public void testOnePaegWithOneBehaviorResult() { + this.getDataCollector().add( + PageResult.buildPageResult(2, + ScenarioStatisticsTest.makeBehaviorList(1))); + AgentPageBriefModel pageBriefModel = (AgentPageBriefModel) this + .getDataCollector().getPageBriefStatistics(2); + assertEquals(2, pageBriefModel.getPageId()); + assertEquals(1, pageBriefModel.getCountFromBegin()); + assertEquals(1, pageBriefModel.getCountThisTime()); + assertEquals(200, pageBriefModel.getMaxResponseTimeFromBegin()); + assertEquals(200, pageBriefModel.getMinResponseTimeFromBegin()); + assertTrue(pageBriefModel.getTimeFrame() >= 0); + assertEquals(200, pageBriefModel.getTotalResponseTimeThisTime()); + assertEquals(200, pageBriefModel.getLatestResponseTime()); + } + + @Test + public void testOnePageWithTwoBehaviorResult() { + this.getDataCollector().add( + PageResult.buildPageResult(2, + ScenarioStatisticsTest.makeBehaviorList(2))); + AgentPageBriefModel pageBriefModel = (AgentPageBriefModel) this + .getDataCollector().getPageBriefStatistics(2); + System.out.println(pageBriefModel.getCountFromBegin()); + assertEquals(2, pageBriefModel.getPageId()); + assertEquals(1, pageBriefModel.getCountFromBegin()); + assertEquals(1, pageBriefModel.getCountThisTime()); + assertEquals(220, pageBriefModel.getMaxResponseTimeFromBegin()); + assertEquals(220, pageBriefModel.getMinResponseTimeFromBegin()); + assertTrue(pageBriefModel.getTimeFrame() >= 0); + assertEquals(220, pageBriefModel.getTotalResponseTimeThisTime()); + assertEquals(220, pageBriefModel.getLatestResponseTime()); + } + + @Test + public void testTwoPageWithStatisticsAtLast() { + this.getDataCollector().add( + PageResult.buildPageResult(2, + ScenarioStatisticsTest.makeBehaviorList(1))); + this.getDataCollector().add( + PageResult.buildPageResult(2, + ScenarioStatisticsTest.makeBehaviorList(2))); + AgentPageBriefModel pageBriefModel = (AgentPageBriefModel) this + .getDataCollector().getPageBriefStatistics(2); + assertEquals(2, pageBriefModel.getPageId()); + assertEquals(2, pageBriefModel.getCountFromBegin()); + assertEquals(2, pageBriefModel.getCountThisTime()); + assertEquals(220, pageBriefModel.getMaxResponseTimeFromBegin()); + assertEquals(200, pageBriefModel.getMinResponseTimeFromBegin()); + assertEquals(420, pageBriefModel.getTotalResponseTimeThisTime()); + assertTrue(pageBriefModel.getTimeFrame() >= 0); + assertEquals(220, pageBriefModel.getLatestResponseTime()); + } + + @Test + public void testTwoPageWithStatisticsIndividually() { + testOnePaegWithOneBehaviorResult(); + this.getDataCollector().add( + PageResult.buildPageResult(2, + ScenarioStatisticsTest.makeBehaviorList(2))); + AgentPageBriefModel model = (AgentPageBriefModel) this.getDataCollector() + .getPageBriefStatistics(2); + assertEquals(2, model.getPageId()); + assertEquals(2, model.getCountFromBegin()); + assertEquals(1, model.getCountThisTime()); + assertEquals(220, model.getMaxResponseTimeFromBegin()); + assertEquals(200, model.getMinResponseTimeFromBegin()); + assertEquals(220, model.getTotalResponseTimeThisTime()); + assertTrue(model.getTimeFrame() >= -0); + assertEquals(220, model.getLatestResponseTime()); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/ScenarioStatisticsTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/ScenarioStatisticsTest.java new file mode 100644 index 00000000..e8680020 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/datastatistics/ScenarioStatisticsTest.java @@ -0,0 +1,173 @@ +package org.bench4q.agent.test.datastatistics; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import org.bench4q.agent.datacollector.DataCollector; +import org.bench4q.agent.datacollector.impl.ScenarioResultCollector; +import org.bench4q.agent.scenario.BehaviorResult; +import org.bench4q.agent.scenario.PageResult; +import org.bench4q.agent.storage.StorageHelper; +import org.bench4q.share.models.agent.statistics.AgentBriefStatusModel; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class ScenarioStatisticsTest { + private DataCollector dataStatistics; + + protected DataCollector getDataStatistics() { + return dataStatistics; + } + + private void setDataStatistics(DataCollector dataStatistics) { + this.dataStatistics = dataStatistics; + } + + public ScenarioStatisticsTest() { + init(); + } + + public void init() { + @SuppressWarnings("resource") + ApplicationContext context = new ClassPathXmlApplicationContext( + "classpath*:/org/bench4q/agent/config/application-context.xml"); + ScenarioResultCollector agentResultDataCollector = new ScenarioResultCollector( + UUID.randomUUID()); + agentResultDataCollector.setStorageHelper((StorageHelper) context + .getBean(StorageHelper.class)); + this.setDataStatistics(agentResultDataCollector); + } + + @Test + public void addZeroBriefTest() { + for (BehaviorResult behaviorResult : makeBehaviorList(0)) { + this.getDataStatistics().add(behaviorResult); + } + AgentBriefStatusModel model = (AgentBriefStatusModel) this + .getDataStatistics().getScenarioBriefStatistics(); + AgentBriefStatusModel modelExpect = makeAllZeroModel(); + modelExpect.setTimeFrame(model.getTimeFrame()); + assertTrue(model.equals(modelExpect)); + } + + @Test + public void addOneBriefTest() throws InterruptedException { + for (BehaviorResult behaviorResult : makeBehaviorList(1)) { + this.getDataStatistics().add(behaviorResult); + } + + Thread.sleep(100); + AgentBriefStatusModel model = (AgentBriefStatusModel) this + .getDataStatistics().getScenarioBriefStatistics(); + AgentBriefStatusModel modelExpect = new AgentBriefStatusModel(); + modelExpect.setTimeFrame(model.getTimeFrame()); + makeUpStatusModelForOneBehavior(modelExpect); + assertTrue(model.equals(modelExpect)); + } + + @Test + public void addTwoBriefTest() throws InterruptedException { + for (BehaviorResult behaviorResult : makeBehaviorList(2)) { + this.getDataStatistics().add(behaviorResult); + } + Thread.sleep(100); + AgentBriefStatusModel model = (AgentBriefStatusModel) this + .getDataStatistics().getScenarioBriefStatistics(); + AgentBriefStatusModel modelExpect = makeUpStatusModelForTwoBehavior(model + .getTimeFrame()); + assertTrue(model.equals(modelExpect)); + } + + public static AgentBriefStatusModel makeUpStatusModelForTwoBehavior( + long timeFrame) { + AgentBriefStatusModel model = new AgentBriefStatusModel(); + model.setTimeFrame(timeFrame); + model.setSuccessThroughputThisTime(1 * 1000 / timeFrame); + model.setFailCountFromBegin(1); + model.setFailThroughputThisTime(1 * 1000 / timeFrame); + model.setMaxResponseTime(200); + model.setMinResponseTime(200); + model.setSuccessCountFromBegin(1); + model.setSuccessCountThisTime(1); + model.setFailCountThisTime(1); + model.setTotalResponseTimeThisTime(200); + model.setTotalSqureResponseTimeThisTime(40000); + return model; + } + + public static void makeUpStatusModelForOneBehavior( + AgentBriefStatusModel model) { + model.setSuccessThroughputThisTime(1 * 1000 / model.getTimeFrame()); + model.setFailCountFromBegin(0); + model.setFailThroughputThisTime(0); + model.setMaxResponseTime(200); + model.setMinResponseTime(200); + model.setSuccessCountFromBegin(1); + model.setSuccessCountThisTime(1); + model.setFailCountThisTime(0); + model.setTotalResponseTimeThisTime(200); + model.setTotalSqureResponseTimeThisTime(40000); + } + + public static AgentBriefStatusModel makeAllZeroModel() { + AgentBriefStatusModel model = new AgentBriefStatusModel(); + model.setSuccessThroughputThisTime(0); + model.setFailCountFromBegin(0); + model.setFailThroughputThisTime(0); + model.setMaxResponseTime(0); + model.setMinResponseTime(0); + model.setTimeFrame(0); + model.setSuccessCountFromBegin(0); + model.setTotalResponseTimeThisTime(0); + model.setSuccessCountThisTime(0); + model.setFailCountThisTime(0); + model.setTotalSqureResponseTimeThisTime(0); + return model; + } + + public static PageResult makePageResultWithBehaviorResult(int count) { + List behaviorResults = makeBehaviorList(count); + return PageResult.buildPageResult(2, behaviorResults); + } + + public static List makeBehaviorList(int count) { + List behaviorResults = new ArrayList(); + for (int i = 0; i < count; i++) { + int statusCode = i % 2 == 0 ? 200 : 400; + behaviorResults.add(buildBehaviorResult(200 + 10 * i, i % 2 == 0, + statusCode, 1, 200 + 10 * i)); + } + return behaviorResults; + } + + public static BehaviorResult buildBehaviorResult(long responseTime, + boolean success, int statusCode, int behaviorId, long startDateTime) { + Date date = new Date(startDateTime); + BehaviorResult result = new BehaviorResult(); + result.setBehaviorName(""); + result.setEndDate(new Date(date.getTime() + responseTime)); + result.setPluginId("Get"); + result.setPluginName("get"); + result.setResponseTime(responseTime); + result.setStartDate(date); + result.setSuccess(success); + result.setShouldBeCountResponseTime(true); + + result.setBehaviorId(behaviorId); + if (result.isSuccess()) { + result.setContentLength(20); + result.setContentType("image"); + } else { + result.setContentLength(0); + result.setContentType(""); + } + result.setStatusCode(statusCode); + return result; + } + +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/model/ModelTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/model/ModelTest.java new file mode 100644 index 00000000..b11ce4b3 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/model/ModelTest.java @@ -0,0 +1,30 @@ +package org.bench4q.agent.test.model; + +import java.io.File; +import java.io.IOException; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.annotation.XmlRootElement; + +import org.bench4q.share.models.agent.scriptrecord.BehaviorModel; +import org.junit.Test; + +import static org.junit.Assert.*; + +@XmlRootElement(name = "modelTest") +public class ModelTest { + + @Test + public void unmarshalVerify() throws IOException, JAXBException { + Object object = JAXBContext + .newInstance(BehaviorModel.class) + .createUnmarshaller() + .unmarshal( + new File("Scripts" + + System.getProperty("file.separator") + + "behaviorModel.xml")); + assertTrue(object instanceof BehaviorModel); + } + +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/model/UserBehaviorModelTest.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/model/UserBehaviorModelTest.java new file mode 100644 index 00000000..c74138d7 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/model/UserBehaviorModelTest.java @@ -0,0 +1,26 @@ +package org.bench4q.agent.test.model; + +import static org.junit.Assert.*; + +import java.io.File; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.bench4q.share.models.agent.scriptrecord.BehaviorModel; +import org.junit.Test; + +public class UserBehaviorModelTest { + + @Test + public void testUnmarshal() throws JAXBException { + Unmarshaller unmarshaller = JAXBContext.newInstance( + BehaviorModel.class).createUnmarshaller(); + Object object = unmarshaller.unmarshal(new File("Scripts" + + System.getProperty("file.separator") + "behaviorModel.xml")); + BehaviorModel userBehaviorModel = (BehaviorModel) object; + System.out.println(userBehaviorModel.getUse()); + assertTrue(object instanceof BehaviorModel); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/TEST_HelloThread.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/TEST_HelloThread.java new file mode 100644 index 00000000..b93f6413 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/TEST_HelloThread.java @@ -0,0 +1,64 @@ +package org.bench4q.agent.test.parameterization; + +import org.bench4q.agent.parameterization.impl.InstanceControler; +import org.bench4q.share.helper.TestHelper; + +public class TEST_HelloThread extends Thread { + InstanceControler ic; + + public TEST_HelloThread() { + ic = new InstanceControler(); + } + + public void run() { + java.util.Random r = new java.util.Random(); + int t = r.nextInt(10000); + System.out.print(Thread.currentThread().getId()); + System.out.println(":" + t); + try { + Thread.sleep(t); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.print(Thread.currentThread().getId()); + System.out.print("\t"); + + String userName = ic + .getParam(""); + String passwordName = ic + .getParam(""); + System.out.print(userName); + System.out.print("\t"); + System.out.println(passwordName); + try { + Thread.sleep(r.nextInt(10000)); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // ic.releaseAll(); + try { + TestHelper.invokePrivate(ic, "releaseAll", null, null); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public static void main(String[] args) { + while (true) { + TEST_HelloThread h1 = new TEST_HelloThread(); + + h1.start(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + // private String name; +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/TEST_UserName.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/TEST_UserName.java new file mode 100644 index 00000000..89e4f2f2 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/TEST_UserName.java @@ -0,0 +1,37 @@ +package org.bench4q.agent.test.parameterization; + +import static org.junit.Assert.*; + +import java.util.HashMap; + +import org.bench4q.agent.parameterization.impl.InstanceControler; +import org.bench4q.agent.parameterization.impl.Para_Table; +import org.bench4q.share.helper.TestHelper; +import org.junit.Test; + +public class TEST_UserName { + + @Test + public void testGetParam() throws Exception { + Para_Table table = new Para_Table(); + String ret = table.getTableColumnValue(java.util.UUID.randomUUID(), + new HashMap(), "file", + "ScenarioParameters\\param1.txt", "0", "sequence", ";", "~", + "2"); + System.out.println(ret); + + InstanceControler ic = new InstanceControler(); + String passwordName = ic + .getParam(""); + System.out.println(passwordName); + assertNotNull(passwordName); + InstanceControler instanceControler = new InstanceControler(); + String password2 = instanceControler + .getParam(""); + System.out.println(password2); + assertNotNull(password2); + assertEquals(Integer.parseInt(passwordName) + 10, + Integer.parseInt(password2)); + TestHelper.invokePrivate(ic, "releaseAll", null, null); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/Test_ParameterizationParser.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/Test_ParameterizationParser.java new file mode 100644 index 00000000..a802129b --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/parameterization/Test_ParameterizationParser.java @@ -0,0 +1,26 @@ +package org.bench4q.agent.test.parameterization; + +import static org.junit.Assert.assertEquals; + +import org.bench4q.agent.parameterization.impl.InstanceControler; +import org.bench4q.agent.parameterization.impl.ParameterizationParser; +import org.bench4q.share.helper.TestHelper; +import org.junit.Test; + +public class Test_ParameterizationParser { + @Test + public void testGetClassName() throws Exception { + String result = (String) TestHelper.invokePrivate( + new ParameterizationParser(), "getCurrentPackageFullName", + null, null); + assertEquals("org.bench4q.agent.parameterization.impl", result); + } + + @Test + public void testParse() { + String result = ParameterizationParser.parse( + "", new InstanceControler()); + System.out.println(result); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/plugin/Test_HttpPlugin.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/plugin/Test_HttpPlugin.java new file mode 100644 index 00000000..930951c4 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/plugin/Test_HttpPlugin.java @@ -0,0 +1,134 @@ +package org.bench4q.agent.test.plugin; + +import java.util.Map; + +import org.apache.commons.httpclient.Cookie; +import org.apache.commons.httpclient.cookie.MalformedCookieException; +import org.bench4q.agent.plugin.basic.http.HttpPlugin; +import org.bench4q.agent.plugin.result.HttpReturn; +import org.bench4q.agent.plugin.result.PluginReturn; +import org.bench4q.share.helper.TestHelper; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class Test_HttpPlugin { + private static final int UnAuthorized = 401; + private HttpPlugin httpPlugin; + + private HttpPlugin getHttpPlugin() { + return httpPlugin; + } + + private void setHttpPlugin(HttpPlugin httpPlugin) { + this.httpPlugin = httpPlugin; + } + + public Test_HttpPlugin() { + this.setHttpPlugin(new HttpPlugin()); + } + + @Test + public void testGet() { + PluginReturn return1 = this.getHttpPlugin().get( + "http://www.baidu.com/s", "wd=ok", "", ""); + assertTrue(return1.isSuccess()); + } + + @Test + public void testPost() { + PluginReturn result = this.getHttpPlugin().post( + "http://133.133.12.2:8080/bench4q-web/login", + "userName=admin;password=admin", null, null, null, null); + assertTrue(result.isSuccess()); + } + + @Test + public void testGetWithActualBehavior() { + PluginReturn result = this + .getHttpPlugin() + .get("http://133.133.12.2:8080/bench4q-web/index.jsp", + "", + "header=Accept|value=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|", + null); + assertTrue(result.isSuccess()); + } + + @Test + public void testSessionAndCookie() throws MalformedCookieException, + IllegalArgumentException { + String loginPageUrl = "http://124.16.137.203:7080/cloudshare_web/login"; + HttpReturn indexReturn = this + .getHttpPlugin() + .get(loginPageUrl, + "", + "header=Accept|value=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|;", + null); + assertEquals(UnAuthorized, indexReturn.getStatusCode()); + assertNotNull(indexReturn.getHeaders()); + logTheCookie("first"); + + HttpReturn loginReturn = this + .getHttpPlugin() + .post(loginPageUrl, + null, + "header=Content-Type|value=application/x-www-form-urlencoded|;header=Content-Length|value=63|;header=Accept|value=text/html,application/xhtml+xml,application/xml|;", + "username=chentienan12%40otcaix.iscas.ac.cn&password=jingcai2008", + null, null); + assertEquals(302, loginReturn.getStatusCode()); + assertNotNull(loginReturn.getHeaders()); + logTheCookie("second"); + + HttpReturn homeReturn = this + .getHttpPlugin() + .get("http://124.16.137.203:7080/cloudshare_web/home", + null, + "header=Accept|value=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|;", + null); + assertEquals(200, homeReturn.getStatusCode()); + logTheCookie("third"); + + HttpReturn ticketReturn = this + .getHttpPlugin() + .post("http://124.16.137.203:7080/cloudshare_web/v2/file/ajax/uploadFiles/-1", + null, + "header=Accept|value=*/*|;" + + "header=Content-Length|value=0|;" + + "header=X-Requested-With|value=XMLHttpRequest|;", + "", + null, + "varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",|leftBoundry=\"ticket\"\": \"|rightBoundry=\",|;"); + assertEquals(200, ticketReturn.getStatusCode()); + assertNotNull(ticketReturn.getRunTimeParams()); + assertEquals(1, ticketReturn.getRunTimeParams().size()); + System.out.println(ticketReturn.getRunTimeParams().get("ticket")); + } + + private void logTheCookie(String times) { + for (Cookie cookie : this.getHttpPlugin().getHttpClient().getState() + .getCookies()) { + System.out.println("Cookie from httpState for " + times + " : " + + cookie.getName() + " : " + cookie.getValue()); + } + } + + @Test + public void testDoExtractResponseVariables() throws Exception { + String respVarsToSave = "varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",|leftBoundry=\"ticket\"\": \"|rightBoundry=\",|;"; + String responseBodyAsString = "{" + "\n" + + "\"ticket\": \"e55de793fc934001b156e97f94ff3eb6\"," + "\n" + + "\"parentId\": 3273," + "\n" + "\"expiresIn\": 300000" + "\n" + + "}"; + @SuppressWarnings("unchecked") + Map nameValueMap = (Map) TestHelper + .invokePrivate(this.getHttpPlugin(), + "doExtractResponseVariables", new Class[] { + String.class, String.class }, new Object[] { + respVarsToSave, responseBodyAsString }); + assertEquals(1, nameValueMap.size()); + assertTrue(nameValueMap.containsKey("ticket")); + System.out.println(nameValueMap.get("ticket")); + assertEquals("e55de793fc934001b156e97f94ff3eb6", + nameValueMap.get("ticket")); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/Test_ScenarioContext.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/Test_ScenarioContext.java new file mode 100644 index 00000000..c2f4f838 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/Test_ScenarioContext.java @@ -0,0 +1,27 @@ +package org.bench4q.agent.test.scenario; + +import static org.junit.Assert.*; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.bench4q.agent.scenario.Scenario; +import org.bench4q.agent.scenario.ScenarioContext; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath*:/org/bench4q/agent/config/application-context.xml" }) +public class Test_ScenarioContext { + + @Test + public void test() { + ScenarioContext context = ScenarioContext.buildScenarioContext( + UUID.randomUUID(), new Scenario(), 20); + assertEquals(10, + context.getExecutor().getKeepAliveTime(TimeUnit.MINUTES)); + assertEquals(20, context.getExecutor().getMaximumPoolSize()); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/utils/Test_ParameterParser.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/utils/Test_ParameterParser.java new file mode 100644 index 00000000..a7bb2c72 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/utils/Test_ParameterParser.java @@ -0,0 +1,202 @@ +package org.bench4q.agent.test.scenario.utils; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.httpclient.NameValuePair; +import org.bench4q.agent.plugin.basic.http.HttpPlugin; +import org.bench4q.agent.scenario.util.ParameterParser; +import org.bench4q.agent.scenario.util.Table; +import org.bench4q.share.helper.TestHelper; +import org.junit.Test; + +public class Test_ParameterParser { + private String testcase = " _nacc=yeah ;_nvid=525d29a534e918cbf04ea7159706a93d;_nvtm=0;_nvsf=0;_nvfi=1;_nlag=zh-cn;_nlmf=1389570024;_nres=1440x900;_nscd=32-bit;_nstm=0;"; + private String testHeaders = "header=Content-Type|value=application/x-www-form-urlencoded|;header=Content-Length|value=63|;header=Accept|value=text/html,application/xhtml+xml,application/xml|;"; + private String testheaderWithUpperCase = "HEADER=Content-Type|Value=application/x-www-form-urlencoded|;header=Content-Length|value=63|;header=Accept|value=text/html,application/xhtml+xml,application/xml|;"; + private static final String TESTCASE1_CONTAIN_SEPARATOR = "header=accept|value=asdfasdf\\|;|;"; + private static final String testcase2 = "header=accept|value=fafsd|;varName=abc|varValue=234|;"; + + private String testcaseWithEscapes = "varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",|;"; + private List expectedNFField = new ArrayList() { + private static final long serialVersionUID = 1L; + { + add("_nacc=yeah"); + add("_nvid=525d29a534e918cbf04ea7159706a93d"); + add("_nvtm=0"); + add("_nvsf=0"); + add("_nvfi=1"); + add("_nlag=zh-cn"); + add("_nlmf=1389570024"); + add("_nres=1440x900"); + add("_nscd=32-bit"); + add("_nstm=0"); + } + }; + + @Test + public void testGetNumberOfEscapeCharacter() throws Exception { + assertEquals(3, "\\\\\\".length()); + assertEquals(2, TestHelper.invokePrivate(null, + "getNumberOfEscapeCharacter", new Class[] { String.class }, + new Object[] { "\\\\" })); + } + + @Test + public void testGetRealTokenForContainSeparator() throws Exception { + List entryList = invokeGetRealTokens( + Table.ESCAPE_ROW_SEPARATOR, TESTCASE1_CONTAIN_SEPARATOR, true); + assertEquals(1, entryList.size()); + assertEquals("header=accept|value=asdfasdf|;", entryList.get(0)); + } + + @Test + public void testGetRealTokenForContainManyEscapse() throws Exception { + List rowList = invokeGetRealTokens(Table.ESCAPE_ROW_SEPARATOR, + testcaseWithEscapes, false); + assertEquals(1, rowList.size()); + assertEquals("varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",", + rowList.get(0)); + + final List columnList = invokeGetRealTokens( + Table.ESCAPE_COLUMN_SEPARATOR, rowList.get(0), false); + assertEquals(2, columnList.size()); + assertEquals("varName=ticket", columnList.get(0)); + assertEquals("varExpression=\"ticket\":\\s*?\"\\w+\",", + columnList.get(1)); + @SuppressWarnings("unchecked") + List> result = (List>) TestHelper + .invokePrivate(null, "extractValueFromWellFormedTable", + new Class[] { List.class }, + new Object[] { new LinkedList>() { + private static final long serialVersionUID = 1L; + { + add(columnList); + } + } }); + // Table.extractValueFromWellFormedTable(new LinkedList>() + // { + // private static final long serialVersionUID = 1L; + // { + // add(columnList); + // } + // }); + assertEquals(1, result.size()); + assertEquals(2, result.get(0).size()); + assertEquals("ticket", result.get(0).get(0)); + assertEquals("\"ticket\":\\s*?\"\\w+\",", result.get(0).get(1)); + } + + @SuppressWarnings("unchecked") + private List invokeGetRealTokens(String separator, String value, + boolean toUnescapeSeparator) throws Exception { + return (List) TestHelper.invokePrivate(null, "getRealTokens", + new Class[] { String.class, String.class, boolean.class }, + new Object[] { separator, value, true }); + } + + @Test + public void testGetRealTokensForMultiSeparator() throws Exception { + List entryList = invokeGetRealTokens( + Table.ESCAPE_ROW_SEPARATOR, testcase2, false); + assertEquals(2, entryList.size()); + assertEquals("header=accept|value=fafsd", entryList.get(0)); + assertEquals("varName=abc|varValue=234", entryList.get(1)); + } + + @Test + public void testGetTableForSeparator() { + List> resultEntries = buildHeaderTable( + TESTCASE1_CONTAIN_SEPARATOR).getRealContent(); + assertEquals(1, resultEntries.size()); + assertEquals(2, resultEntries.get(0).size()); + assertEquals("accept", resultEntries.get(0).get(0)); + assertEquals("asdfasdf|;", resultEntries.get(0).get(1)); + } + + @Test + public void testGetTableForMultipleHeader() { + List> resultEntries = buildHeaderTable(testcase2) + .getRealContent(); + assertEquals(2, resultEntries.size()); + assertEquals("fafsd", resultEntries.get(0).get(1)); + assertEquals("accept", resultEntries.get(0).get(0)); + assertEquals("234", resultEntries.get(1).get(1)); + assertEquals("abc", resultEntries.get(1).get(0)); + } + + private Table buildHeaderTable(String value) { + return ParameterParser.buildTable(value, new LinkedList() { + private static final long serialVersionUID = -6734367739974282326L; + { + add("header"); + add("value"); + } + }); + } + + @Test + public void testGetTableWithManyEscapse() { + List> resultTable = buildHeaderTable(testcaseWithEscapes) + .getRealContent(); + assertEquals(1, resultTable.size()); + assertEquals(2, resultTable.get(0).size()); + assertEquals("ticket", resultTable.get(0).get(0)); + assertEquals("\"ticket\":\\s*?\"\\w+\",", resultTable.get(0).get(1)); + } + + @Test + public void testParseParam() { + List result = ParameterParser.buildNField(testcase); + assertEquals(10, result.size()); + for (int i = 0; i < result.size(); i++) { + assertEquals(result.get(i), expectedNFField.get(i)); + System.out.println(result.get(i)); + } + } + + @Test + public void testGetHeadersWithRightCase() throws Exception { + @SuppressWarnings("unchecked") + List nvPairs = (List) TestHelper + .invokePrivate(new HttpPlugin(), "parseHeaders", + new Class[] { String.class }, + new Object[] { testHeaders }); + + assertEquals(3, nvPairs.size()); + assertEquals("Content-Type", nvPairs.get(0).getName()); + assertEquals("application/x-www-form-urlencoded", nvPairs.get(0) + .getValue()); + assertEquals("Content-Length", nvPairs.get(1).getName()); + assertEquals("63", nvPairs.get(1).getValue()); + assertEquals("Accept", nvPairs.get(2).getName()); + assertEquals("text/html,application/xhtml+xml,application/xml", nvPairs + .get(2).getValue()); + } + + @Test + public void testGetHeadersWithUpperCase() throws Exception { + @SuppressWarnings("unchecked") + List nvPairs = (List) TestHelper + .invokePrivate(new HttpPlugin(), "parseHeaders", + new Class[] { String.class }, + new Object[] { testheaderWithUpperCase }); + assertEquals(3, nvPairs.size()); + assertEquals("Content-Type", nvPairs.get(0).getName()); + assertEquals("application/x-www-form-urlencoded", nvPairs.get(0) + .getValue()); + assertEquals("Content-Length", nvPairs.get(1).getName()); + assertEquals("63", nvPairs.get(1).getValue()); + assertEquals("Accept", nvPairs.get(2).getName()); + assertEquals("text/html,application/xhtml+xml,application/xml", nvPairs + .get(2).getValue()); + } + + @Test + public void testParseResponseVariables() { + + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/utils/Test_RegularExpression.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/utils/Test_RegularExpression.java new file mode 100644 index 00000000..0597fc4d --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/utils/Test_RegularExpression.java @@ -0,0 +1,31 @@ +package org.bench4q.agent.test.scenario.utils; + +import static org.junit.Assert.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; + +public class Test_RegularExpression { + String regex1 = "(?i)((^[aeiou])|(\\s+[aeiou]))\\w+?[aeiou]\\b"; + String regex2 = "(?i)\\w+?[aeiou]"; + String regex3 = "(?i)(\\s+[aeiou])\\w+?[aeiou]\b"; + String regex4 = "(?i)(^[aeiou])\\w+?[aeiou]\b"; + String target1 = "Arline ate eight apples and one orange while anita hadn't any"; + String target2 = "Arline ate"; + + @Test + public void test() { + + Pattern pattern = Pattern.compile(regex2); + + Matcher matcher = pattern.matcher(target1); + System.out.println(matcher.matches()); + matcher.reset(); + while (matcher.find()) { + System.out.println(matcher.group()); + } + fail(); + } +} diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/storage/TestDoubleBufferStorage.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/storage/TestDoubleBufferStorage.java new file mode 100644 index 00000000..3559adc2 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/storage/TestDoubleBufferStorage.java @@ -0,0 +1,204 @@ +package org.bench4q.agent.test.storage; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.bench4q.agent.storage.Buffer; +import org.bench4q.agent.storage.DoubleBufferStorage; +import org.bench4q.share.helper.TestHelper; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath*:/org/bench4q/agent/config/application-context.xml" }) +public class TestDoubleBufferStorage { + private DoubleBufferStorage doubleBufferStorage; + private static String SAVE_DIR = "StorageTest" + + System.getProperty("file.separator"); + private static final String INPUT_FILE_PATH = SAVE_DIR + "testInput.txt"; + private static String SAVE_PATH = SAVE_DIR + "test.txt"; + + private DoubleBufferStorage getDoubleBufferStorage() { + return doubleBufferStorage; + } + + @Autowired + private void setDoubleBufferStorage(DoubleBufferStorage doubleBufferStorage) { + this.doubleBufferStorage = doubleBufferStorage; + } + + public TestDoubleBufferStorage() throws IOException { + File dir = new File(SAVE_DIR); + if (!dir.exists()) { + dir.mkdirs(); + } + File outPutFile = new File(SAVE_PATH); + if (!outPutFile.exists()) { + outPutFile.createNewFile(); + } + File inputFile = new File(INPUT_FILE_PATH); + if (!inputFile.exists()) { + inputFile.createNewFile(); + } + } + + @After + public void cleanUp() { + File file = new File(SAVE_DIR + "test.txt"); + if (file.exists()) { + file.delete(); + } + for (int i = 0; i < 4; ++i) { + String realSavePathString = this.getDoubleBufferStorage() + .calculateSavePath(SAVE_PATH, i); + File output = new File(realSavePathString); + if (output.exists()) { + output.delete(); + } + } + } + + @SuppressWarnings("unchecked") + @Test + public void testWriteWithLittleContent() throws Exception { + this.getDoubleBufferStorage().writeFile("test", SAVE_PATH); + assertEquals( + 48 * 1024 - 4, + ((Buffer) invokePrivateMethod(this.getDoubleBufferStorage() + .getClass(), this.getDoubleBufferStorage(), + "getCurrentBuffer", null, null)).getRemainSize()); + List buffers = ((List) invokePrivateMethod(this + .getDoubleBufferStorage().getClass(), + this.getDoubleBufferStorage(), "getBufferList", null, null)); + for (int i = 0; i < buffers.size() + && i != (Integer) invokePrivateMethod(this + .getDoubleBufferStorage().getClass(), + this.getDoubleBufferStorage(), "getCurrentBufferIndex", + null, null); i++) { + assertEquals(48 * 1024, buffers.get(i).getRemainSize()); + } + } + + @Test + @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) + public void testWriteWithJustLargerThanOneBufferContent() throws Exception { + String realSavePathString = this.getDoubleBufferStorage() + .calculateSavePath( + SAVE_PATH, + (Integer) invokePrivateMethod(this + .getDoubleBufferStorage().getClass(), this + .getDoubleBufferStorage(), + "getCurrentBufferIndex", null, null)); + doWriteFile(95); + while (!this.getDoubleBufferStorage().forTest.isSuccess()) { + Thread.sleep(1000); + } + String readContent = this.getDoubleBufferStorage().readFiles( + realSavePathString); + assertTrue(readContent.length() <= 48 * 1024); + assertTrue(readContent.length() >= 46 * 1024); + assertTrue(readContent.indexOf("encoding") > 0); + Buffer currentBuffer = (Buffer) invokePrivateMethod(this + .getDoubleBufferStorage().getClass(), + this.getDoubleBufferStorage(), "getCurrentBuffer", null, null); + System.out.println(currentBuffer.getCurrentPos()); + System.out + .println((Integer) invokePrivateMethod(this + .getDoubleBufferStorage().getClass(), this + .getDoubleBufferStorage(), "getCurrentBufferIndex", + null, null)); + assertTrue(currentBuffer.getCurrentPos() == 1563); + } + + private void doWriteFile(int size) { + String saveContent = this.getDoubleBufferStorage().readFiles( + INPUT_FILE_PATH); + for (int i = 0; i < size; i++) { + this.getDoubleBufferStorage().writeFile(saveContent, SAVE_PATH); + } + } + + @Test + @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) + public void testWriteWithJustLargerThanTwoBufferContent() + throws InterruptedException { + doWriteFile(92 * 2 + 2); + while (!this.getDoubleBufferStorage().forTest.isSuccess()) { + Thread.sleep(1000); + } + assertEquals(47932 * 2, getResultLength()); + } + + @Test + @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) + public void testWriteContentLargerThanThree() throws InterruptedException { + doWriteFile(92 * 3 + 2); + while (!this.getDoubleBufferStorage().forTest.isSuccess()) { + Thread.sleep(1000); + } + int resultLength = getResultLength(); + assertEquals(47932 * 3, resultLength); + } + + private int getResultLength() { + int resultLength = 0; + for (int i = 0; i < 4; i++) { + String path = this.getDoubleBufferStorage().calculateSavePath( + SAVE_PATH, i); + if (!new File(path).exists()) { + continue; + } + String readContentString = this.getDoubleBufferStorage().readFiles( + path); + resultLength += readContentString.length(); + } + return resultLength; + } + + @Test + public void testChangeBuffer() throws Exception { + @SuppressWarnings("unchecked") + List buffers = (List) invokePrivateMethod(this + .getDoubleBufferStorage().getClass(), + this.getDoubleBufferStorage(), "getBufferList", null, null); + buffers.get(0).setCurrentPos(48 * 1024 - 1220); + buffers.get(1).setCurrentPos(0); + invokePrivateMethod(getDoubleBufferStorage().getClass(), + this.getDoubleBufferStorage(), "setCurrentBufferIndex", + new Class[] { int.class }, new Object[] { 0 }); + invokePrivateMethod(this.getDoubleBufferStorage().getClass(), + this.getDoubleBufferStorage(), "changeToTheMaxRemainBuffer", + null, null); + + assertEquals(1220, buffers.get(0).getRemainSize()); + assertEquals(48 * 1024, buffers.get(1).getRemainSize()); + assertEquals( + 1, + invokePrivateMethod(this.getDoubleBufferStorage().getClass(), + this.getDoubleBufferStorage(), "getCurrentBufferIndex", + null, null)); + } + + private static Object invokePrivateMethod(Class containerClass, + Object targetObject, String methodName, Class[] paramClasses, + Object[] params) throws Exception { + return TestHelper.invokePrivate(targetObject, methodName, paramClasses, + params); + } + + @Test + public void testReadFiles() { + String content = this.getDoubleBufferStorage().readFiles( + INPUT_FILE_PATH); + assertEquals(content.length(), 521); + } +} diff --git a/Bench4Q-Agent/src/test/resources/test-storage-context.xml b/Bench4Q-Agent/src/test/resources/test-storage-context.xml new file mode 100644 index 00000000..dcef0042 --- /dev/null +++ b/Bench4Q-Agent/src/test/resources/test-storage-context.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/frame1.html b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/frame1.html new file mode 100644 index 00000000..a513d1fa --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/frame1.html @@ -0,0 +1,8 @@ + + +frame1 + + + No this picture + + \ No newline at end of file diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/frameTestCase.html b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/frameTestCase.html new file mode 100644 index 00000000..64bf46f7 --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/frameTestCase.html @@ -0,0 +1,16 @@ + + +Bench4Q Test Case + + + + + + + No this one + No this one + No this one + + + + \ No newline at end of file diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/1.jpg b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/1.jpg new file mode 100644 index 00000000..9723ecba Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/1.jpg differ diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/2.jpg b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/2.jpg new file mode 100644 index 00000000..fea436b2 Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/2.jpg differ diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/3.jpg b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/3.jpg new file mode 100644 index 00000000..8ddaaee2 Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/3.jpg differ diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/4.jpg b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/4.jpg new file mode 100644 index 00000000..c599a8fc Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/4.jpg differ diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/5.jpg b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/5.jpg new file mode 100644 index 00000000..82ddf33b Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/5.jpg differ diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/6.jpg b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/6.jpg new file mode 100644 index 00000000..c2c09c35 Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/images/6.jpg differ diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/script/agentTable.js b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/script/agentTable.js new file mode 100644 index 00000000..8ebdd8ca --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/script/agentTable.js @@ -0,0 +1,94 @@ +var table= $('#agents'); +$('.datatable').dataTable({ + "sDom": "<'row-fluid'<'span6'l><'span6'f>>t<'row-fluid'<'span12 center'p>>", + "sPaginationType": "bootstrap", + "oLanguage": { + "sLengthMenu": "_MENU_ records per page" + } +} ); + + +$('.btn-setting').click(function(e){ +e.preventDefault(); +$("#agentParam").modal('show'); +}); +$(document).ready(function() { + loadAgents(table); + +}); +function cancel(){ + $("#agentParam").modal('hide'); +} +function loadAgents() { + table.dataTable().fnClearTable(); + $.post("loadAgents", {}, function(data) { + if (data!=null) { + for (var i = 0; i'+ + ''+ + ''+ + '' + ); + var els = $('a', nPaging); + $(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler ); + $(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler ); + }, + + "fnUpdate": function ( oSettings, fnDraw ) { + var iListLength = 5; + var oPaging = oSettings.oInstance.fnPagingInfo(); + var an = oSettings.aanFeatures.p; + var i, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2); + + if ( oPaging.iTotalPages < iListLength) { + iStart = 1; + iEnd = oPaging.iTotalPages; + } + else if ( oPaging.iPage <= iHalf ) { + iStart = 1; + iEnd = iListLength; + } else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) { + iStart = oPaging.iTotalPages - iListLength + 1; + iEnd = oPaging.iTotalPages; + } else { + iStart = oPaging.iPage - iHalf + 1; + iEnd = iStart + iListLength - 1; + } + + for ( i=0, iLen=an.length ; i'+j+'') + .insertBefore( $('li:last', an[i])[0] ) + .bind('click', function (e) { + e.preventDefault(); + oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength; + fnDraw( oSettings ); + } ); + } + + // add / remove disabled classes from the static elements + if ( oPaging.iPage === 0 ) { + $('li:first', an[i]).addClass('disabled'); + } else { + $('li:first', an[i]).removeClass('disabled'); + } + + if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) { + $('li:last', an[i]).addClass('disabled'); + } else { + $('li:last', an[i]).removeClass('disabled'); + } + } + } + } +}); +function loadProperties(){ + jQuery.i18n.properties({// 加载资浏览器语言对应的资源文件 + name:'i18n', // 资源文件名称 + path:'i18n/', // 资源文件路径 + mode:'map', // 用 Map 的方式使用资源文件中的值 + } ); + } diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/style/bootstrap-cerulean.css b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/style/bootstrap-cerulean.css new file mode 100644 index 00000000..281ed9fa --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/style/bootstrap-cerulean.css @@ -0,0 +1,4453 @@ +@import url(http://fonts.googleapis.com/css?family=Karla|Ubuntu); +/*! + * Bootstrap v2.0.4 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} +audio:not([controls]) { + display: none; +} +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +a:hover, +a:active { + outline: 0; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} +#map_canvas img { + max-width: none; +} +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} +button, +input { + *overflow: visible; + line-height: normal; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} +textarea { + overflow: auto; + vertical-align: top; +} +.clearfix { + *zoom: 1; +} +.clearfix:before, +.clearfix:after { + display: table; + content: ""; +} +.clearfix:after { + clear: both; +} +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.input-block-level { + display: block; + width: 100%; + min-height: 28px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} +body { + margin: 0; + font-family: "Ubuntu", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 18px; + color: #555555; + background-color: #ffffff; + text-shadow:0 -1px 1px rgba(0, 0, 0, 0.2) +} +a { + color: #369bd7; + text-decoration: none; +} +a:hover { + color: #2071a1; + text-decoration: underline; +} +.row { + margin-left: -20px; + *zoom: 1; +} +.row:before, +.row:after { + display: table; + content: ""; +} +.row:after { + clear: both; +} +[class*="span"] { + float: left; + margin-left: 20px; +} +.container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} +.span12 { + width: 940px; +} +.span11 { + width: 860px; +} +.span10 { + width: 780px; +} +.span9 { + width: 700px; +} +.span8 { + width: 620px; +} +.span7 { + width: 540px; +} +.span6 { + width: 460px; +} +.span5 { + width: 380px; +} +.span4 { + width: 300px; +} +.span3 { + width: 220px; +} +.span2 { + width: 140px; +} +.span1 { + width: 60px; +} +.offset12 { + margin-left: 980px; +} +.offset11 { + margin-left: 900px; +} +.offset10 { + margin-left: 820px; +} +.offset9 { + margin-left: 740px; +} +.offset8 { + margin-left: 660px; +} +.offset7 { + margin-left: 580px; +} +.offset6 { + margin-left: 500px; +} +.offset5 { + margin-left: 420px; +} +.offset4 { + margin-left: 340px; +} +.offset3 { + margin-left: 260px; +} +.offset2 { + margin-left: 180px; +} +.offset1 { + margin-left: 100px; +} +.row-fluid { + width: 100%; + *zoom: 1; +} +.row-fluid:before, +.row-fluid:after { + display: table; + content: ""; +} +.row-fluid:after { + clear: both; +} +.row-fluid [class*="span"] { + display: block; + width: 100%; + min-height: 28px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + float: left; + margin-left: 2.127659574%; + *margin-left: 2.0744680846382977%; +} +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} +.row-fluid .span12 { + width: 99.99999998999999%; + *width: 99.94680850063828%; +} +.row-fluid .span11 { + width: 91.489361693%; + *width: 91.4361702036383%; +} +.row-fluid .span10 { + width: 82.97872339599999%; + *width: 82.92553190663828%; +} +.row-fluid .span9 { + width: 74.468085099%; + *width: 74.4148936096383%; +} +.row-fluid .span8 { + width: 65.95744680199999%; + *width: 65.90425531263828%; +} +.row-fluid .span7 { + width: 57.446808505%; + *width: 57.3936170156383%; +} +.row-fluid .span6 { + width: 48.93617020799999%; + *width: 48.88297871863829%; +} +.row-fluid .span5 { + width: 40.425531911%; + *width: 40.3723404216383%; +} +.row-fluid .span4 { + width: 31.914893614%; + *width: 31.8617021246383%; +} +.row-fluid .span3 { + width: 23.404255317%; + *width: 23.3510638276383%; +} +.row-fluid .span2 { + width: 14.89361702%; + *width: 14.8404255306383%; +} +.row-fluid .span1 { + width: 6.382978723%; + *width: 6.329787233638298%; +} +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} +.container:before, +.container:after { + display: table; + content: ""; +} +.container:after { + clear: both; +} +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} +.container-fluid:before, +.container-fluid:after { + display: table; + content: ""; +} +.container-fluid:after { + clear: both; +} +p { + margin: 0 0 9px; +} +p small { + font-size: 11px; + color: #999999; +} +.lead { + margin-bottom: 18px; + font-size: 20px; + font-weight: 200; + line-height: 27px; +} +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + font-family: 'Karla', sans-serif; + font-weight: bold; + color: #317eac; + text-rendering: optimizelegibility; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + color: #999999; +} +h1 { + font-size: 30px; + line-height: 36px; +} +h1 small { + font-size: 18px; +} +h2 { + font-size: 24px; + line-height: 36px; +} +h2 small { + font-size: 18px; +} +h3 { + font-size: 18px; + line-height: 27px; +} +h3 small { + font-size: 14px; +} +h4, +h5, +h6 { + line-height: 18px; +} +h4 { + font-size: 14px; +} +h4 small { + font-size: 12px; +} +h5 { + font-size: 12px; +} +h6 { + font-size: 11px; + color: #999999; + text-transform: uppercase; +} +.page-header { + padding-bottom: 17px; + margin: 18px 0; + border-bottom: 1px solid #f5f5f5; +} +.page-header h1 { + line-height: 1; +} +ul, +ol { + padding: 0; + margin: 0 0 9px 25px; +} +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} +ul { + list-style: disc; +} +ol { + list-style: decimal; +} +li { + line-height: 18px; +} +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} +dl { + margin-bottom: 18px; +} +dt, +dd { + line-height: 18px; +} +dt { + font-weight: bold; + line-height: 17px; +} +dd { + margin-left: 9px; +} +.dl-horizontal dt { + float: left; + width: 120px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.dl-horizontal dd { + margin-left: 130px; +} +hr { + margin: 18px 0; + border: 0; + border-top: 1px solid #f5f5f5; + border-bottom: 1px solid #ffffff; +} +strong { + font-weight: bold; +} +em { + font-style: italic; +} +.muted { + color: #999999; +} +abbr[title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 0 0 0 15px; + margin: 0 0 18px; + border-left: 5px solid #f5f5f5; +} +blockquote p { + margin-bottom: 0; + font-size: 16px; + font-weight: 300; + line-height: 22.5px; +} +blockquote small { + display: block; + line-height: 18px; + color: #999999; +} +blockquote small:before { + content: '\2014 \00A0'; +} +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #f5f5f5; + border-left: 0; +} +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} +address { + display: block; + margin-bottom: 18px; + font-style: normal; + line-height: 18px; +} +small { + font-size: 100%; +} +cite { + font-style: normal; +} +code, +pre { + padding: 0 3px 2px; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +code { + padding: 2px 4px; + color: #d14; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} +pre { + display: block; + padding: 8.5px; + margin: 0 0 9px; + font-size: 12.025px; + line-height: 18px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +pre.prettyprint { + margin-bottom: 18px; +} +pre code { + padding: 0; + color: inherit; + background-color: transparent; + border: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +form { + margin: 0 0 18px; +} +fieldset { + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 27px; + font-size: 19.5px; + line-height: 36px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +legend small { + font-size: 13.5px; + color: #999999; +} +label, +input, +button, +select, +textarea { + font-size: 13px; + font-weight: normal; + line-height: 18px; +} +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} +label { + display: block; + margin-bottom: 5px; +} +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 18px; + padding: 4px; + margin-bottom: 9px; + font-size: 13px; + line-height: 18px; + color: #555555; +} +input, +textarea { + width: 210px; +} +textarea { + height: auto; +} +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); +} +input[type="radio"], +input[type="checkbox"] { + margin: 3px 0; + *margin-top: 0; + /* IE7 */ + + line-height: normal; + cursor: pointer; +} +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} +.uneditable-textarea { + width: auto; + height: auto; +} +select, +input[type="file"] { + height: 28px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 28px; +} +select { + width: 220px; + border: 1px solid #bbb; +} +select[multiple], +select[size] { + height: auto; +} +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.radio, +.checkbox { + min-height: 18px; + padding-left: 18px; +} +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -18px; +} +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} +.input-mini { + width: 60px; +} +.input-small { + width: 90px; +} +.input-medium { + width: 150px; +} +.input-large { + width: 210px; +} +.input-xlarge { + width: 270px; +} +.input-xxlarge { + width: 530px; +} +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} +input, +textarea, +.uneditable-input { + margin-left: 0; +} +input.span12, textarea.span12, .uneditable-input.span12 { + width: 930px; +} +input.span11, textarea.span11, .uneditable-input.span11 { + width: 850px; +} +input.span10, textarea.span10, .uneditable-input.span10 { + width: 770px; +} +input.span9, textarea.span9, .uneditable-input.span9 { + width: 690px; +} +input.span8, textarea.span8, .uneditable-input.span8 { + width: 610px; +} +input.span7, textarea.span7, .uneditable-input.span7 { + width: 530px; +} +input.span6, textarea.span6, .uneditable-input.span6 { + width: 450px; +} +input.span5, textarea.span5, .uneditable-input.span5 { + width: 370px; +} +input.span4, textarea.span4, .uneditable-input.span4 { + width: 290px; +} +input.span3, textarea.span3, .uneditable-input.span3 { + width: 210px; +} +input.span2, textarea.span2, .uneditable-input.span2 { + width: 130px; +} +input.span1, textarea.span1, .uneditable-input.span1 { + width: 50px; +} +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #f5f5f5; + border-color: #ddd; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} +.control-group.warning > label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #1c628b; +} +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #1c628b; + border-color: #1c628b; +} +.control-group.warning .checkbox:focus, +.control-group.warning .radio:focus, +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #134461; + -webkit-box-shadow: 0 0 6px #369bd7; + -moz-box-shadow: 0 0 6px #369bd7; + box-shadow: 0 0 6px #369bd7; +} +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #1c628b; + background-color: #8bc5e8; + border-color: #1c628b; +} +.control-group.error > label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #bd4247; +} +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #bd4247; + border-color: #bd4247; +} +.control-group.error .checkbox:focus, +.control-group.error .radio:focus, +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #983538; + -webkit-box-shadow: 0 0 6px #d88e90; + -moz-box-shadow: 0 0 6px #d88e90; + box-shadow: 0 0 6px #d88e90; +} +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #bd4247; + background-color: #eddbe3; + border-color: #bd4247; +} +.control-group.success > label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #669533; +} +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #669533; + border-color: #669533; +} +.control-group.success .checkbox:focus, +.control-group.success .radio:focus, +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #4c6f26; + -webkit-box-shadow: 0 0 6px #99ca63; + -moz-box-shadow: 0 0 6px #99ca63; + box-shadow: 0 0 6px #99ca63; +} +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #669533; + background-color: #ccddbb; + border-color: #669533; +} +input:focus:required:invalid, +textarea:focus:required:invalid, +select:focus:required:invalid { + color: #b94a48; + border-color: #ee5f5b; +} +input:focus:required:invalid:focus, +textarea:focus:required:invalid:focus, +select:focus:required:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} +.form-actions { + padding: 17px 20px 18px; + margin-top: 18px; + margin-bottom: 18px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} +.form-actions:before, +.form-actions:after { + display: table; + content: ""; +} +.form-actions:after { + clear: both; +} +.uneditable-input { + overflow: hidden; + white-space: nowrap; + cursor: not-allowed; + background-color: #ffffff; + border-color: #eee; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} +:-moz-placeholder { + color: #999999; +} +:-ms-input-placeholder { + color: #999999; +} +::-webkit-input-placeholder { + color: #999999; +} +.help-block, +.help-inline { + color: #555555; +} +.help-block { + display: block; + margin-bottom: 9px; +} +.help-inline { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; + vertical-align: middle; + padding-left: 5px; +} +.input-prepend, +.input-append { + margin-bottom: 5px; +} +.input-prepend input, +.input-append input, +.input-prepend select, +.input-append select, +.input-prepend .uneditable-input, +.input-append .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: middle; + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-prepend input:focus, +.input-append input:focus, +.input-prepend select:focus, +.input-append select:focus, +.input-prepend .uneditable-input:focus, +.input-append .uneditable-input:focus { + z-index: 2; +} +.input-prepend .uneditable-input, +.input-append .uneditable-input { + border-left-color: #ccc; +} +.input-prepend .add-on, +.input-append .add-on { + display: inline-block; + width: auto; + height: 18px; + min-width: 16px; + padding: 4px 5px; + font-weight: normal; + line-height: 18px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + vertical-align: middle; + background-color: #f5f5f5; + border: 1px solid #ccc; +} +.input-prepend .add-on, +.input-append .add-on, +.input-prepend .btn, +.input-append .btn { + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.input-prepend .active, +.input-append .active { + background-color: #bede9c; + border-color: #73a839; +} +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-append .uneditable-input { + border-right-color: #ccc; + border-left-color: #eee; +} +.input-append .add-on:last-child, +.input-append .btn:last-child { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 14px; + -moz-border-radius: 14px; + border-radius: 14px; +} +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; + margin-bottom: 0; +} +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} +.form-search label, +.form-inline label { + display: inline-block; +} +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} +.control-group { + margin-bottom: 9px; +} +legend + .control-group { + margin-top: 18px; + -webkit-margin-top-collapse: separate; +} +.form-horizontal .control-group { + margin-bottom: 18px; + *zoom: 1; +} +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + content: ""; +} +.form-horizontal .control-group:after { + clear: both; +} +.form-horizontal .control-label { + float: left; + width: 140px; + padding-top: 5px; + text-align: right; +} +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 160px; + *margin-left: 0; +} +.form-horizontal .controls:first-child { + *padding-left: 160px; +} +.form-horizontal .help-block { + margin-top: 9px; + margin-bottom: 0; +} +.form-horizontal .form-actions { + padding-left: 160px; +} +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} +.table { + width: 100%; + margin-bottom: 18px; +} +.table th, +.table td { + padding: 8px; + line-height: 18px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table th { + font-weight: bold; +} +.table thead th { + vertical-align: bottom; +} +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} +.table tbody + tbody { + border-top: 2px solid #dddddd; +} +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapsed; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} +.table-bordered thead:first-child tr:first-child th:first-child, +.table-bordered tbody:first-child tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} +.table-bordered thead:first-child tr:first-child th:last-child, +.table-bordered tbody:first-child tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} +.table-bordered thead:last-child tr:last-child th:first-child, +.table-bordered tbody:last-child tr:last-child td:first-child { + -webkit-border-radius: 0 0 0 4px; + -moz-border-radius: 0 0 0 4px; + border-radius: 0 0 0 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} +.table-bordered thead:last-child tr:last-child th:last-child, +.table-bordered tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} +.table-striped tbody tr:nth-child(odd) td, +.table-striped tbody tr:nth-child(odd) th { + background-color: #f9f9f9; +} +.table tbody tr:hover td, +.table tbody tr:hover th { + background-color: #f5f5f5; +} +table .span1 { + float: none; + width: 44px; + margin-left: 0; +} +table .span2 { + float: none; + width: 124px; + margin-left: 0; +} +table .span3 { + float: none; + width: 204px; + margin-left: 0; +} +table .span4 { + float: none; + width: 284px; + margin-left: 0; +} +table .span5 { + float: none; + width: 364px; + margin-left: 0; +} +table .span6 { + float: none; + width: 444px; + margin-left: 0; +} +table .span7 { + float: none; + width: 524px; + margin-left: 0; +} +table .span8 { + float: none; + width: 604px; + margin-left: 0; +} +table .span9 { + float: none; + width: 684px; + margin-left: 0; +} +table .span10 { + float: none; + width: 764px; + margin-left: 0; +} +table .span11 { + float: none; + width: 844px; + margin-left: 0; +} +table .span12 { + float: none; + width: 924px; + margin-left: 0; +} +table .span13 { + float: none; + width: 1004px; + margin-left: 0; +} +table .span14 { + float: none; + width: 1084px; + margin-left: 0; +} +table .span15 { + float: none; + width: 1164px; + margin-left: 0; +} +table .span16 { + float: none; + width: 1244px; + margin-left: 0; +} +table .span17 { + float: none; + width: 1324px; + margin-left: 0; +} +table .span18 { + float: none; + width: 1404px; + margin-left: 0; +} +table .span19 { + float: none; + width: 1484px; + margin-left: 0; +} +table .span20 { + float: none; + width: 1564px; + margin-left: 0; +} +table .span21 { + float: none; + width: 1644px; + margin-left: 0; +} +table .span22 { + float: none; + width: 1724px; + margin-left: 0; +} +table .span23 { + float: none; + width: 1804px; + margin-left: 0; +} +table .span24 { + float: none; + width: 1884px; + margin-left: 0; +} +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} +[class^="icon-"]:last-child, +[class*=" icon-"]:last-child { + *margin-left: 0; +} +.icon-white { + background-image: url("../img/glyphicons-halflings-white.png"); +} +.icon-glass { + background-position: 0 0; +} +.icon-music { + background-position: -24px 0; +} +.icon-search { + background-position: -48px 0; +} +.icon-envelope { + background-position: -72px 0; +} +.icon-heart { + background-position: -96px 0; +} +.icon-star { + background-position: -120px 0; +} +.icon-star-empty { + background-position: -144px 0; +} +.icon-user { + background-position: -168px 0; +} +.icon-film { + background-position: -192px 0; +} +.icon-th-large { + background-position: -216px 0; +} +.icon-th { + background-position: -240px 0; +} +.icon-th-list { + background-position: -264px 0; +} +.icon-ok { + background-position: -288px 0; +} +.icon-remove { + background-position: -312px 0; +} +.icon-zoom-in { + background-position: -336px 0; +} +.icon-zoom-out { + background-position: -360px 0; +} +.icon-off { + background-position: -384px 0; +} +.icon-signal { + background-position: -408px 0; +} +.icon-cog { + background-position: -432px 0; +} +.icon-trash { + background-position: -456px 0; +} +.icon-home { + background-position: 0 -24px; +} +.icon-file { + background-position: -24px -24px; +} +.icon-time { + background-position: -48px -24px; +} +.icon-road { + background-position: -72px -24px; +} +.icon-download-alt { + background-position: -96px -24px; +} +.icon-download { + background-position: -120px -24px; +} +.icon-upload { + background-position: -144px -24px; +} +.icon-inbox { + background-position: -168px -24px; +} +.icon-play-circle { + background-position: -192px -24px; +} +.icon-repeat { + background-position: -216px -24px; +} +.icon-refresh { + background-position: -240px -24px; +} +.icon-list-alt { + background-position: -264px -24px; +} +.icon-lock { + background-position: -287px -24px; +} +.icon-flag { + background-position: -312px -24px; +} +.icon-headphones { + background-position: -336px -24px; +} +.icon-volume-off { + background-position: -360px -24px; +} +.icon-volume-down { + background-position: -384px -24px; +} +.icon-volume-up { + background-position: -408px -24px; +} +.icon-qrcode { + background-position: -432px -24px; +} +.icon-barcode { + background-position: -456px -24px; +} +.icon-tag { + background-position: 0 -48px; +} +.icon-tags { + background-position: -25px -48px; +} +.icon-book { + background-position: -48px -48px; +} +.icon-bookmark { + background-position: -72px -48px; +} +.icon-print { + background-position: -96px -48px; +} +.icon-camera { + background-position: -120px -48px; +} +.icon-font { + background-position: -144px -48px; +} +.icon-bold { + background-position: -167px -48px; +} +.icon-italic { + background-position: -192px -48px; +} +.icon-text-height { + background-position: -216px -48px; +} +.icon-text-width { + background-position: -240px -48px; +} +.icon-align-left { + background-position: -264px -48px; +} +.icon-align-center { + background-position: -288px -48px; +} +.icon-align-right { + background-position: -312px -48px; +} +.icon-align-justify { + background-position: -336px -48px; +} +.icon-list { + background-position: -360px -48px; +} +.icon-indent-left { + background-position: -384px -48px; +} +.icon-indent-right { + background-position: -408px -48px; +} +.icon-facetime-video { + background-position: -432px -48px; +} +.icon-picture { + background-position: -456px -48px; +} +.icon-pencil { + background-position: 0 -72px; +} +.icon-map-marker { + background-position: -24px -72px; +} +.icon-adjust { + background-position: -48px -72px; +} +.icon-tint { + background-position: -72px -72px; +} +.icon-edit { + background-position: -96px -72px; +} +.icon-share { + background-position: -120px -72px; +} +.icon-check { + background-position: -144px -72px; +} +.icon-move { + background-position: -168px -72px; +} +.icon-step-backward { + background-position: -192px -72px; +} +.icon-fast-backward { + background-position: -216px -72px; +} +.icon-backward { + background-position: -240px -72px; +} +.icon-play { + background-position: -264px -72px; +} +.icon-pause { + background-position: -288px -72px; +} +.icon-stop { + background-position: -312px -72px; +} +.icon-forward { + background-position: -336px -72px; +} +.icon-fast-forward { + background-position: -360px -72px; +} +.icon-step-forward { + background-position: -384px -72px; +} +.icon-eject { + background-position: -408px -72px; +} +.icon-chevron-left { + background-position: -432px -72px; +} +.icon-chevron-right { + background-position: -456px -72px; +} +.icon-plus-sign { + background-position: 0 -96px; +} +.icon-minus-sign { + background-position: -24px -96px; +} +.icon-remove-sign { + background-position: -48px -96px; +} +.icon-ok-sign { + background-position: -72px -96px; +} +.icon-question-sign { + background-position: -96px -96px; +} +.icon-info-sign { + background-position: -120px -96px; +} +.icon-screenshot { + background-position: -144px -96px; +} +.icon-remove-circle { + background-position: -168px -96px; +} +.icon-ok-circle { + background-position: -192px -96px; +} +.icon-ban-circle { + background-position: -216px -96px; +} +.icon-arrow-left { + background-position: -240px -96px; +} +.icon-arrow-right { + background-position: -264px -96px; +} +.icon-arrow-up { + background-position: -289px -96px; +} +.icon-arrow-down { + background-position: -312px -96px; +} +.icon-share-alt { + background-position: -336px -96px; +} +.icon-resize-full { + background-position: -360px -96px; +} +.icon-resize-small { + background-position: -384px -96px; +} +.icon-plus { + background-position: -408px -96px; +} +.icon-minus { + background-position: -433px -96px; +} +.icon-asterisk { + background-position: -456px -96px; +} +.icon-exclamation-sign { + background-position: 0 -120px; +} +.icon-gift { + background-position: -24px -120px; +} +.icon-leaf { + background-position: -48px -120px; +} +.icon-fire { + background-position: -72px -120px; +} +.icon-eye-open { + background-position: -96px -120px; +} +.icon-eye-close { + background-position: -120px -120px; +} +.icon-warning-sign { + background-position: -144px -120px; +} +.icon-plane { + background-position: -168px -120px; +} +.icon-calendar { + background-position: -192px -120px; +} +.icon-random { + background-position: -216px -120px; +} +.icon-comment { + background-position: -240px -120px; +} +.icon-magnet { + background-position: -264px -120px; +} +.icon-chevron-up { + background-position: -288px -120px; +} +.icon-chevron-down { + background-position: -313px -119px; +} +.icon-retweet { + background-position: -336px -120px; +} +.icon-shopping-cart { + background-position: -360px -120px; +} +.icon-folder-close { + background-position: -384px -120px; +} +.icon-folder-open { + background-position: -408px -120px; +} +.icon-resize-vertical { + background-position: -432px -119px; +} +.icon-resize-horizontal { + background-position: -456px -118px; +} +.icon-hdd { + background-position: 0 -144px; +} +.icon-bullhorn { + background-position: -24px -144px; +} +.icon-bell { + background-position: -48px -144px; +} +.icon-certificate { + background-position: -72px -144px; +} +.icon-thumbs-up { + background-position: -96px -144px; +} +.icon-thumbs-down { + background-position: -120px -144px; +} +.icon-hand-right { + background-position: -144px -144px; +} +.icon-hand-left { + background-position: -168px -144px; +} +.icon-hand-up { + background-position: -192px -144px; +} +.icon-hand-down { + background-position: -216px -144px; +} +.icon-circle-arrow-right { + background-position: -240px -144px; +} +.icon-circle-arrow-left { + background-position: -264px -144px; +} +.icon-circle-arrow-up { + background-position: -288px -144px; +} +.icon-circle-arrow-down { + background-position: -312px -144px; +} +.icon-globe { + background-position: -336px -144px; +} +.icon-wrench { + background-position: -360px -144px; +} +.icon-tasks { + background-position: -384px -144px; +} +.icon-filter { + background-position: -408px -144px; +} +.icon-briefcase { + background-position: -432px -144px; +} +.icon-fullscreen { + background-position: -456px -144px; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle { + *margin-bottom: -3px; +} +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; + opacity: 0.3; + filter: alpha(opacity=30); +} +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} +.dropdown:hover .caret, +.open .caret { + opacity: 1; + filter: alpha(opacity=100); +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 4px 0; + margin: 1px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 8px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} +.dropdown-menu a { + display: block; + padding: 3px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: #333333; + white-space: nowrap; +} +.dropdown-menu li > a:hover, +.dropdown-menu .active > a, +.dropdown-menu .active > a:hover { + color: #ffffff; + text-decoration: none; + background-color: #369bd7; +} +.open { + *z-index: 1000; +} +.open > .dropdown-menu { + display: block; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: "\2191"; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +.typeahead { + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #eee; + border: 1px solid rgba(0, 0, 0, 0.05); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -ms-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -ms-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} +.collapse.in { + height: auto; +} +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 18px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.btn { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; + padding: 4px 10px 4px; + margin-bottom: 0; + font-size: 13px; + line-height: 18px; + *line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(top, #ffffff, #e6e6e6); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #e6e6e6; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + border: 1px solid #cccccc; + *border: 0; + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *margin-left: .3em; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); +} +.btn:hover, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + background-color: #e6e6e6; + *background-color: #d9d9d9; +} +.btn:active, +.btn.active { + background-color: #cccccc \9; +} +.btn:first-child { + *margin-left: 0; +} +.btn:hover { + color: #333333; + text-decoration: none; + background-color: #e6e6e6; + *background-color: #d9d9d9; + /* Buttons in IE7 don't get borders, so darken on hover */ + + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -ms-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn.active, +.btn:active { + background-color: #e6e6e6; + background-color: #d9d9d9 \9; + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); +} +.btn.disabled, +.btn[disabled] { + cursor: default; + background-color: #e6e6e6; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn-large { + padding: 9px 14px; + font-size: 15px; + line-height: normal; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +.btn-large [class^="icon-"] { + margin-top: 1px; +} +.btn-small { + padding: 5px 9px; + font-size: 11px; + line-height: 16px; +} +.btn-small [class^="icon-"] { + margin-top: -1px; +} +.btn-mini { + padding: 2px 6px; + font-size: 11px; + line-height: 14px; +} +.btn-primary, +.btn-primary:hover, +.btn-warning, +.btn-warning:hover, +.btn-danger, +.btn-danger:hover, +.btn-success, +.btn-success:hover, +.btn-info, +.btn-info:hover, +.btn-inverse, +.btn-inverse:hover { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} +.btn { + border-color: #ccc; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn-primary { + background-color: #368bd7; + background-image: -moz-linear-gradient(top, #369bd7, #3673d7); + background-image: -ms-linear-gradient(top, #369bd7, #3673d7); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#369bd7), to(#3673d7)); + background-image: -webkit-linear-gradient(top, #369bd7, #3673d7); + background-image: -o-linear-gradient(top, #369bd7, #3673d7); + background-image: linear-gradient(top, #369bd7, #3673d7); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#369bd7', endColorstr='#3673d7', GradientType=0); + border-color: #3673d7 #3673d7 #2050a1; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #3673d7; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-primary:hover, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + background-color: #3673d7; + *background-color: #2866cb; +} +.btn-primary:active, +.btn-primary.active { + background-color: #245bb6 \9; +} +.btn-warning { + background-color: #dd5600; + background-image: -moz-linear-gradient(top, #dd5600, #dd5600); + background-image: -ms-linear-gradient(top, #dd5600, #dd5600); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#dd5600), to(#dd5600)); + background-image: -webkit-linear-gradient(top, #dd5600, #dd5600); + background-image: -o-linear-gradient(top, #dd5600, #dd5600); + background-image: linear-gradient(top, #dd5600, #dd5600); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dd5600', endColorstr='#dd5600', GradientType=0); + border-color: #dd5600 #dd5600 #913800; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #dd5600; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-warning:hover, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + background-color: #dd5600; + *background-color: #c44c00; +} +.btn-warning:active, +.btn-warning.active { + background-color: #aa4200 \9; +} +.btn-danger { + background-color: #c32627; + background-image: -moz-linear-gradient(top, #c71c22, #bd362f); + background-image: -ms-linear-gradient(top, #c71c22, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#c71c22), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #c71c22, #bd362f); + background-image: -o-linear-gradient(top, #c71c22, #bd362f); + background-image: linear-gradient(top, #c71c22, #bd362f); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c71c22', endColorstr='#bd362f', GradientType=0); + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #bd362f; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-danger:hover, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + background-color: #bd362f; + *background-color: #a9302a; +} +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} +.btn-success { + background-color: #65a643; + background-image: -moz-linear-gradient(top, #73a839, #51a351); + background-image: -ms-linear-gradient(top, #73a839, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#73a839), to(#51a351)); + background-image: -webkit-linear-gradient(top, #73a839, #51a351); + background-image: -o-linear-gradient(top, #73a839, #51a351); + background-image: linear-gradient(top, #73a839, #51a351); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#73a839', endColorstr='#51a351', GradientType=0); + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #51a351; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-success:hover, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + background-color: #51a351; + *background-color: #499249; +} +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} +.btn-info { + background-color: #6d76b3; + background-image: -moz-linear-gradient(top, #9760b3, #2f96b4); + background-image: -ms-linear-gradient(top, #9760b3, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#9760b3), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #9760b3, #2f96b4); + background-image: -o-linear-gradient(top, #9760b3, #2f96b4); + background-image: linear-gradient(top, #9760b3, #2f96b4); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#9760b3', endColorstr='#2f96b4', GradientType=0); + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #2f96b4; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-info:hover, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + background-color: #2f96b4; + *background-color: #2a85a0; +} +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} +.btn-inverse { + background-color: #a27a28; + background-image: -moz-linear-gradient(top, #f7b42c, #222222); + background-image: -ms-linear-gradient(top, #f7b42c, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f7b42c), to(#222222)); + background-image: -webkit-linear-gradient(top, #f7b42c, #222222); + background-image: -o-linear-gradient(top, #f7b42c, #222222); + background-image: linear-gradient(top, #f7b42c, #222222); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7b42c', endColorstr='#222222', GradientType=0); + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #222222; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-inverse:hover, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + background-color: #222222; + *background-color: #151515; +} +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} +button.btn, +input[type="submit"].btn { + *padding-top: 2px; + *padding-bottom: 2px; +} +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} +.btn-group { + position: relative; + *zoom: 1; + *margin-left: .3em; +} +.btn-group:before, +.btn-group:after { + display: table; + content: ""; +} +.btn-group:after { + clear: both; +} +.btn-group:first-child { + *margin-left: 0; +} +.btn-group + .btn-group { + margin-left: 5px; +} +.btn-toolbar { + margin-top: 9px; + margin-bottom: 9px; +} +.btn-toolbar .btn-group { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} +.btn-group > .btn { + position: relative; + float: left; + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; +} +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topleft: 6px; + border-top-left-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-left-radius: 6px; +} +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + -moz-border-radius-topright: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + -moz-border-radius-bottomright: 6px; + border-bottom-right-radius: 6px; +} +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + *padding-top: 4px; + *padding-bottom: 4px; +} +.btn-group > .btn-mini.dropdown-toggle { + padding-left: 5px; + padding-right: 5px; +} +.btn-group > .btn-small.dropdown-toggle { + *padding-top: 4px; + *padding-bottom: 4px; +} +.btn-group > .btn-large.dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); +} +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #3673d7; +} +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #dd5600; +} +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} +.btn .caret { + margin-top: 7px; + margin-left: 0; +} +.btn:hover .caret, +.open.btn-group .caret { + opacity: 1; + filter: alpha(opacity=100); +} +.btn-mini .caret { + margin-top: 5px; +} +.btn-small .caret { + margin-top: 6px; +} +.btn-large .caret { + margin-top: 6px; + border-left-width: 5px; + border-right-width: 5px; + border-top-width: 5px; +} +.dropup .btn-large .caret { + border-bottom: 5px solid #000000; + border-top: 0; +} +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 0.75; + filter: alpha(opacity=75); +} +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 18px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #8bc5e8; + border: 1px solid #7ed0e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + color: #1c628b; +} +.alert-heading { + color: inherit; +} +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 18px; +} +.alert-success { + background-color: #ccddbb; + border-color: #c6d4aa; + color: #669533; +} +.alert-danger, +.alert-error { + background-color: #eddbe3; + border-color: #e8d1df; + color: #bd4247; +} +.alert-info { + background-color: #edebe1; + border-color: #e0d9cb; + color: #817b58; +} +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} +.alert-block p + p { + margin-top: 5px; +} +.nav { + margin-left: 0; + margin-bottom: 18px; + list-style: none; +} +.nav > li > a { + display: block; +} +.nav > li > a:hover { + text-decoration: none; + background-color: #f5f5f5; +} +.nav > .pull-right { + float: right; +} +.nav .nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 18px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} +.nav li + .nav-header { + margin-top: 9px; +} +.nav-list { + padding-left: 15px; + padding-right: 15px; + margin-bottom: 0; +} +.nav-list > li > a, +.nav-list .nav-header { + margin-left: -15px; + margin-right: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.nav-list > li > a { + padding: 3px 15px; +} +.nav-list > .active > a, +.nav-list > .active > a:hover { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #369bd7; +} +.nav-list [class^="icon-"] { + margin-right: 2px; +} +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 8px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} +.nav-tabs, +.nav-pills { + *zoom: 1; +} +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + content: ""; +} +.nav-tabs:after, +.nav-pills:after { + clear: both; +} +.nav-tabs > li, +.nav-pills > li { + float: left; +} +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + margin-bottom: -1px; +} +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 18px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #f5f5f5 #f5f5f5 #dddddd; +} +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover { + color: #555555; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +.nav-pills > .active > a, +.nav-pills > .active > a:hover { + color: #ffffff; + background-color: #369bd7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li > a { + margin-right: 0; +} +.nav-tabs.nav-stacked { + border-bottom: 0; +} +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.nav-tabs.nav-stacked > li > a:hover { + border-color: #ddd; + z-index: 2; +} +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} +.nav-pills .dropdown-menu { + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.nav-tabs .dropdown-toggle .caret, +.nav-pills .dropdown-toggle .caret { + border-top-color: #369bd7; + border-bottom-color: #369bd7; + margin-top: 6px; +} +.nav-tabs .dropdown-toggle:hover .caret, +.nav-pills .dropdown-toggle:hover .caret { + border-top-color: #2071a1; + border-bottom-color: #2071a1; +} +.nav-tabs .active .dropdown-toggle .caret, +.nav-pills .active .dropdown-toggle .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} +.nav > .dropdown.active > a:hover { + color: #000000; + cursor: pointer; +} +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} +.tabs-stacked .open > a:hover { + border-color: #999999; +} +.tabbable { + *zoom: 1; +} +.tabbable:before, +.tabbable:after { + display: table; + content: ""; +} +.tabbable:after { + clear: both; +} +.tab-content { + overflow: auto; +} +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} +.tab-content > .active, +.pill-content > .active { + display: block; +} +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.tabs-below > .nav-tabs > li > a:hover { + border-bottom-color: transparent; + border-top-color: #ddd; +} +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover { + border-color: transparent #ddd #ddd #ddd; +} +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} +.tabs-left > .nav-tabs > li > a:hover { + border-color: #f5f5f5 #dddddd #f5f5f5 #f5f5f5; +} +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.tabs-right > .nav-tabs > li > a:hover { + border-color: #f5f5f5 #f5f5f5 #f5f5f5 #dddddd; +} +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} +.navbar { + *position: relative; + *z-index: 2; + overflow: visible; + margin-bottom: 18px; +} +.navbar-inner { + min-height: 40px; + padding-left: 20px; + padding-right: 20px; + background-color: #50a8dc; + background-image: -moz-linear-gradient(top, #61b0df, #369bd7); + background-image: -ms-linear-gradient(top, #61b0df, #369bd7); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#61b0df), to(#369bd7)); + background-image: -webkit-linear-gradient(top, #61b0df, #369bd7); + background-image: -o-linear-gradient(top, #61b0df, #369bd7); + background-image: linear-gradient(top, #61b0df, #369bd7); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61b0df', endColorstr='#369bd7', GradientType=0); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.25), inset 0 -1px 0 rgba(0,0,0,.1); + -moz-box-shadow: 0 1px 3px rgba(0,0,0,.25), inset 0 -1px 0 rgba(0,0,0,.1); + box-shadow: 0 1px 3px rgba(0,0,0,.25), inset 0 -1px 0 rgba(0,0,0,.1); +} +.navbar .container { + width: auto; +} +.nav-collapse.collapse { + height: auto; +} +.navbar { + color: #f5f5f5; +} +.navbar .brand:hover { + text-decoration: none; +} +.navbar .brand { + float: left; + display: block; + padding: 8px 20px 12px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + line-height: 1; + color: #f5f5f5; +} +.navbar .navbar-text { + margin-bottom: 0; + line-height: 40px; +} +.navbar .navbar-link { + color: #f5f5f5; +} +.navbar .navbar-link:hover { + color: #ffffff; +} +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} +.navbar .btn-group .btn { + margin: 0; +} +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} +.navbar-form:before, +.navbar-form:after { + display: table; + content: ""; +} +.navbar-form:after { + clear: both; +} +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} +.navbar-form input, +.navbar-form select { + display: inline-block; + margin-bottom: 0; +} +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 6px; + white-space: nowrap; +} +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} +.navbar-search { + position: relative; + float: left; + margin-top: 6px; + margin-bottom: 0; +} +.navbar-search .search-query { + padding: 4px 9px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + color: #ffffff; + background-color: #a0d0ec; + border: 1px solid #288ecb; + -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); + -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); + box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; +} +.navbar-search .search-query:-moz-placeholder { + color: #ffffff; +} +.navbar-search .search-query:-ms-input-placeholder { + color: #ffffff; +} +.navbar-search .search-query::-webkit-input-placeholder { + color: #ffffff; +} +.navbar-search .search-query:focus, +.navbar-search .search-query.focused { + padding: 5px 10px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + outline: 0; +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-left: 0; + padding-right: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} +.navbar-fixed-top { + top: 0; +} +.navbar-fixed-bottom { + bottom: 0; +} +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} +.navbar .nav.pull-right { + float: right; +} +.navbar .nav > li { + display: block; + float: left; +} +.navbar .nav > li > a { + float: none; + padding: 9px 10px 11px; + line-height: 19px; + color: #f5f5f5; + text-decoration: none; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-right: 1px solid #3887B3; + border-left: 1px solid #3887B3; +} +.navbar .btn { + display: inline-block; + padding: 4px 10px 4px; + margin: 5px 5px 6px; + line-height: 18px; +} +.navbar .btn-group { + margin: 0; + padding: 5px 5px 6px; +} +.navbar .nav > li > a:hover { + background-color: transparent; + color: #ffffff; + text-decoration: none; +} +.navbar .nav .active > a, +.navbar .nav .active > a:hover { + color: #ffffff; + text-decoration: none; + background-color: rgba(0, 0, 0, 0.2); +} +.navbar .divider-vertical { + height: 40px; + width: 1px; + margin: 0 9px; + overflow: hidden; + background-color: #369bd7; + border-right: 1px solid #61b0df; +} +.navbar .nav.pull-right { + margin-left: 10px; + margin-right: 0; +} +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-left: 5px; + margin-right: 5px; + background-color: #50a8dc; + background-image: -moz-linear-gradient(top, #61b0df, #369bd7); + background-image: -ms-linear-gradient(top, #61b0df, #369bd7); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#61b0df), to(#369bd7)); + background-image: -webkit-linear-gradient(top, #61b0df, #369bd7); + background-image: -o-linear-gradient(top, #61b0df, #369bd7); + background-image: linear-gradient(top, #61b0df, #369bd7); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61b0df', endColorstr='#369bd7', GradientType=0); + border-color: #369bd7 #369bd7 #2071a1; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #369bd7; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); + box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); +} +.navbar .btn-navbar:hover, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + background-color: #369bd7; + *background-color: #288ecb; +} +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #2480b6 \9; +} +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} +.navbar .dropdown-menu:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 9px; +} +.navbar .dropdown-menu:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 10px; +} +.navbar-fixed-bottom .dropdown-menu:before { + border-top: 7px solid #ccc; + border-top-color: rgba(0, 0, 0, 0.2); + border-bottom: 0; + bottom: -7px; + top: auto; +} +.navbar-fixed-bottom .dropdown-menu:after { + border-top: 6px solid #ffffff; + border-bottom: 0; + bottom: -6px; + top: auto; +} +.navbar .nav li.dropdown .dropdown-toggle .caret, +.navbar .nav li.dropdown.open .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} +.navbar .nav li.dropdown.active .caret { + opacity: 1; + filter: alpha(opacity=100); +} +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + background-color: transparent; +} +.navbar .nav li.dropdown.active > .dropdown-toggle:hover { + color: #ffffff; +} +.navbar .pull-right .dropdown-menu, +.navbar .dropdown-menu.pull-right { + left: auto; + right: 0; +} +.navbar .pull-right .dropdown-menu:before, +.navbar .dropdown-menu.pull-right:before { + left: auto; + right: 12px; +} +.navbar .pull-right .dropdown-menu:after, +.navbar .dropdown-menu.pull-right:after { + left: auto; + right: 13px; +} +.breadcrumb { + padding: 7px 14px; + margin: 0 0 18px; + list-style: none; + background-color: #fbfbfb; + background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); + background-image: linear-gradient(top, #ffffff, #f5f5f5); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); + border: 1px solid #ddd; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} +.breadcrumb li { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; + text-shadow: 0 1px 0 #ffffff; +} +.breadcrumb .divider { + padding: 0 5px; + color: #999999; +} +.breadcrumb .active a { + color: #333333; +} +.pagination { + height: 36px; + margin: 18px 0; +} +.pagination ul { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; + margin-left: 0; + margin-bottom: 0; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} +.pagination li { + display: inline; +} +.pagination a { + float: left; + padding: 0 14px; + line-height: 34px; + text-decoration: none; + border: 1px solid #ddd; + border-left-width: 0; +} +.pagination a:hover, +.pagination .active a { + background-color: #f5f5f5; +} +.pagination .active a { + color: #999999; + cursor: default; +} +.pagination .disabled span, +.pagination .disabled a, +.pagination .disabled a:hover { + color: #999999; + background-color: transparent; + cursor: default; +} +.pagination li:first-child a { + border-left-width: 1px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.pagination li:last-child a { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.pagination-centered { + text-align: center; +} +.pagination-right { + text-align: right; +} +.pager { + margin-left: 0; + margin-bottom: 18px; + list-style: none; + text-align: center; + *zoom: 1; +} +.pager:before, +.pager:after { + display: table; + content: ""; +} +.pager:after { + clear: both; +} +.pager li { + display: inline; +} +.pager a { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +.pager a:hover { + text-decoration: none; + background-color: #f5f5f5; +} +.pager .next a { + float: right; +} +.pager .previous a { + float: left; +} +.pager .disabled a, +.pager .disabled a:hover { + color: #999999; + background-color: #fff; + cursor: default; +} +.modal-open .dropdown-menu { + z-index: 2050; +} +.modal-open .dropdown.open { + *z-index: 2050; +} +.modal-open .popover { + z-index: 2060; +} +.modal-open .tooltip { + z-index: 2070; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 1050; + overflow: auto; + width: 560px; + margin: -250px 0 0 -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + /* IE6-7 */ + + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -ms-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} +.modal.fade.in { + top: 50%; +} +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} +.modal-header .close { + margin-top: 2px; +} +.modal-body { + overflow-y: auto; + max-height: 400px; + padding: 15px; +} +.modal-form { + margin-bottom: 0; +} +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + *zoom: 1; +} +.modal-footer:before, +.modal-footer:after { + display: table; + content: ""; +} +.modal-footer:after { + clear: both; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.tooltip { + position: absolute; + z-index: 1020; + display: block; + visibility: visible; + padding: 5px; + font-size: 11px; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} +.tooltip.top { + margin-top: -2px; +} +.tooltip.right { + margin-left: 2px; +} +.tooltip.bottom { + margin-top: 2px; +} +.tooltip.left { + margin-left: -2px; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #000000; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + padding: 5px; +} +.popover.top { + margin-top: -5px; +} +.popover.right { + margin-left: 5px; +} +.popover.bottom { + margin-top: 5px; +} +.popover.left { + margin-left: -5px; +} +.popover.top .arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #000000; +} +.popover.right .arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #000000; +} +.popover.bottom .arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; +} +.popover.left .arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} +.popover .arrow { + position: absolute; + width: 0; + height: 0; +} +.popover-inner { + padding: 3px; + width: 280px; + overflow: hidden; + background: #000000; + background: rgba(0, 0, 0, 0.8); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); +} +.popover-title { + padding: 9px 15px; + line-height: 1; + background-color: #f5f5f5; + border-bottom: 1px solid #eee; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; +} +.popover-content { + padding: 14px; + background-color: #ffffff; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.popover-content p, +.popover-content ul, +.popover-content ol { + margin-bottom: 0; +} +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} +.thumbnails:before, +.thumbnails:after { + display: table; + content: ""; +} +.thumbnails:after { + clear: both; +} +.row-fluid .thumbnails { + margin-left: 0; +} +.thumbnails > li { + float: left; + margin-bottom: 18px; + margin-left: 20px; +} +.thumbnail { + display: block; + padding: 4px; + line-height: 1; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); +} +a.thumbnail:hover { + border-color: #369bd7; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} +.thumbnail > img { + display: block; + max-width: 100%; + margin-left: auto; + margin-right: auto; +} +.thumbnail .caption { + padding: 9px; +} +.label, +.badge { + font-size: 10.998px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + vertical-align: baseline; + white-space: nowrap; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #999999; +} +.label { + padding: 1px 4px 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.badge { + padding: 1px 9px 2px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} +a.label:hover, +a.badge:hover { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label-important, +.badge-important { + background-color: #bd4247; +} +.label-important[href], +.badge-important[href] { + background-color: #983538; +} +.label-warning, +.badge-warning { + background-color: #dd5600; +} +.label-warning[href], +.badge-warning[href] { + background-color: #aa4200; +} +.label-success, +.badge-success { + background-color: #669533; +} +.label-success[href], +.badge-success[href] { + background-color: #4c6f26; +} +.label-info, +.badge-info { + background-color: #817b58; +} +.label-info[href], +.badge-info[href] { + background-color: #625e43; +} +.label-inverse, +.badge-inverse { + background-color: #333333; +} +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 18px; + margin-bottom: 18px; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(top, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.progress .bar { + width: 0%; + height: 18px; + color: #ffffff; + font-size: 12px; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -ms-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(top, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -ms-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-danger .bar { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); +} +.progress-danger.progress-striped .bar { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-success .bar { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -ms-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(top, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); +} +.progress-success.progress-striped .bar { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-info .bar { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(top, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); +} +.progress-info.progress-striped .bar { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-warning .bar { + background-color: #f16e1a; + background-image: -moz-linear-gradient(top, #ff7d2b, #dd5600); + background-image: -ms-linear-gradient(top, #ff7d2b, #dd5600); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff7d2b), to(#dd5600)); + background-image: -webkit-linear-gradient(top, #ff7d2b, #dd5600); + background-image: -o-linear-gradient(top, #ff7d2b, #dd5600); + background-image: linear-gradient(top, #ff7d2b, #dd5600); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff7d2b', endColorstr='#dd5600', GradientType=0); +} +.progress-warning.progress-striped .bar { + background-color: #ff7d2b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.accordion { + margin-bottom: 18px; +} +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.accordion-heading { + border-bottom: 0; +} +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} +.accordion-toggle { + cursor: pointer; +} +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} +.carousel { + position: relative; + margin-bottom: 18px; + line-height: 1; +} +.carousel-inner { + overflow: hidden; + width: 100%; + position: relative; +} +.carousel .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -ms-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel .item > img { + display: block; + line-height: 1; +} +.carousel .active, +.carousel .next, +.carousel .prev { + display: block; +} +.carousel .active { + left: 0; +} +.carousel .next, +.carousel .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel .next { + left: 100%; +} +.carousel .prev { + left: -100%; +} +.carousel .next.left, +.carousel .prev.right { + left: 0; +} +.carousel .active.left { + left: -100%; +} +.carousel .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} +.carousel-control.right { + left: auto; + right: 15px; +} +.carousel-control:hover { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-caption { + position: absolute; + left: 0; + right: 0; + bottom: 0; + padding: 10px 15px 5px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} +.carousel-caption h4, +.carousel-caption p { + color: #ffffff; +} +.hero-unit { + padding: 60px; + margin-bottom: 30px; + background-color: #f5f5f5; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + color: inherit; + letter-spacing: -1px; +} +.hero-unit p { + font-size: 18px; + font-weight: 200; + line-height: 27px; + color: inherit; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.hide { + display: none; +} +.show { + display: block; +} +.invisible { + visibility: hidden; +} +.navbar,.top-block { + font-family: 'Karla', sans-serif; +} +.navbar .navbar-inner { + background-color: #3f9fd9; +} +.navbar-inner{ + background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(0,0,0,0.15) 50%, rgba(30,30,30,0) 100%); +background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0)), color-stop(50%,rgba(0,0,0,0.15)), color-stop(100%,rgba(30,30,30,0))); +background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(0,0,0,0.15) 50%,rgba(30,30,30,0) 100%); +background: -o-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(0,0,0,0.15) 50%,rgba(30,30,30,0) 100%); +background: -ms-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(0,0,0,0.15) 50%,rgba(30,30,30,0) 100%); +background: linear-gradient(to bottom, rgba(255,255,255,0) 0%,rgba(0,0,0,0.15) 50%,rgba(30,30,30,0) 100%); +filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#001e1e1e',GradientType=0 ); +} +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.active.open > .dropdown-toggle { + background-color: rgba(0, 0, 0, 0.2); +} +.navbar .search-query { + border: 1px solid #2480b6; +} +.navbar .nav-collapse.in > .nav > li .dropdown-menu a { + color: #ffffff; +} +.navbar .nav-collapse.in > .nav > li .dropdown-menu a:hover { + color: #ffffff; +} +.navbar .nav-collapse.in .nav li > a { + color: #ffffff; +} +.navbar .nav-collapse.in .nav li > a:hover { + background-color: #2B7CAC; +} +.navbar .btn-navbar:hover { + background-color: #cccccc; +} +div.subnav { + font-family: 'Karla', sans-serif; +} +.btn { + background-color: #ffffff; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(5%, #ffffff), to(#ffffff)); + background-image: -webkit-linear-gradient(#ffffff, #ffffff 5%, #ffffff); + background-image: -moz-linear-gradient(top, #ffffff, #ffffff 5%, #ffffff); + background-image: -ms-linear-gradient(#ffffff, #ffffff 5%, #ffffff); + background-image: -o-linear-gradient(#ffffff, #ffffff 5%, #ffffff); + background-image: linear-gradient(#ffffff, #ffffff 5%, #ffffff); + background-repeat: no-repeat; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#ffffff', GradientType=0); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} +.btn:hover { + background-position: 0 0; +} +.btn-primary { + background-color: #43a1da; + background-image: -moz-linear-gradient(top, #4ba6db, #369bd7); + background-image: -ms-linear-gradient(top, #4ba6db, #369bd7); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#4ba6db), to(#369bd7)); + background-image: -webkit-linear-gradient(top, #4ba6db, #369bd7); + background-image: -o-linear-gradient(top, #4ba6db, #369bd7); + background-image: linear-gradient(top, #4ba6db, #369bd7); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4ba6db', endColorstr='#369bd7', GradientType=0); + border-color: #369bd7 #369bd7 #2071a1; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #369bd7; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-primary:hover, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + background-color: #369bd7; + *background-color: #288ecb; +} +.btn-primary:active, +.btn-primary.active { + background-color: #2480b6 \9; +} +.btn-info { + background-color: #9e6ab8; + background-image: -moz-linear-gradient(top, #a271bb, #9760b3); + background-image: -ms-linear-gradient(top, #a271bb, #9760b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#a271bb), to(#9760b3)); + background-image: -webkit-linear-gradient(top, #a271bb, #9760b3); + background-image: -o-linear-gradient(top, #a271bb, #9760b3); + background-image: linear-gradient(top, #a271bb, #9760b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#a271bb', endColorstr='#9760b3', GradientType=0); + border-color: #9760b3 #9760b3 #6f4086; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #9760b3; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-info:hover, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + background-color: #9760b3; + *background-color: #8b51a9; +} +.btn-info:active, +.btn-info.active { + background-color: #7d4898 \9; +} +.btn-success { + background-color: #7bb33d; + background-image: -moz-linear-gradient(top, #80bb3f, #73a839); + background-image: -ms-linear-gradient(top, #80bb3f, #73a839); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#80bb3f), to(#73a839)); + background-image: -webkit-linear-gradient(top, #80bb3f, #73a839); + background-image: -o-linear-gradient(top, #80bb3f, #73a839); + background-image: linear-gradient(top, #80bb3f, #73a839); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80bb3f', endColorstr='#73a839', GradientType=0); + border-color: #73a839 #73a839 #4c6f26; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #73a839; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-success:hover, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + background-color: #73a839; + *background-color: #669533; +} +.btn-success:active, +.btn-success.active { + background-color: #59822c \9; +} +.btn-warning { + background-color: #ec5c00; + background-image: -moz-linear-gradient(top, #f76000, #dd5600); + background-image: -ms-linear-gradient(top, #f76000, #dd5600); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f76000), to(#dd5600)); + background-image: -webkit-linear-gradient(top, #f76000, #dd5600); + background-image: -o-linear-gradient(top, #f76000, #dd5600); + background-image: linear-gradient(top, #f76000, #dd5600); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f76000', endColorstr='#dd5600', GradientType=0); + border-color: #dd5600 #dd5600 #913800; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #dd5600; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-warning:hover, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + background-color: #dd5600; + *background-color: #c44c00; +} +.btn-warning:active, +.btn-warning.active { + background-color: #aa4200 \9; +} +.btn-danger { + background-color: #d41e24; + background-image: -moz-linear-gradient(top, #dd1f26, #c71c22); + background-image: -ms-linear-gradient(top, #dd1f26, #c71c22); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#dd1f26), to(#c71c22)); + background-image: -webkit-linear-gradient(top, #dd1f26, #c71c22); + background-image: -o-linear-gradient(top, #dd1f26, #c71c22); + background-image: linear-gradient(top, #dd1f26, #c71c22); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dd1f26', endColorstr='#c71c22', GradientType=0); + border-color: #c71c22 #c71c22 #841317; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #c71c22; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-danger:hover, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + background-color: #c71c22; + *background-color: #b1191e; +} +.btn-danger:active, +.btn-danger.active { + background-color: #9a161a \9; +} +.btn-inverse { + background-color: #f8b93b; + background-image: -moz-linear-gradient(top, #f8bd45, #f7b42c); + background-image: -ms-linear-gradient(top, #f8bd45, #f7b42c); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f8bd45), to(#f7b42c)); + background-image: -webkit-linear-gradient(top, #f8bd45, #f7b42c); + background-image: -o-linear-gradient(top, #f8bd45, #f7b42c); + background-image: linear-gradient(top, #f8bd45, #f7b42c); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8bd45', endColorstr='#f7b42c', GradientType=0); + border-color: #f7b42c #f7b42c #cf8d08; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #f7b42c; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-inverse:hover, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + background-color: #f7b42c; + *background-color: #f6ab13; +} +.btn-inverse:active, +.btn-inverse.active { + background-color: #e79e09 \9; +} +i[class^="icon-"] { + opacity: 0.8; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.hide { + display: none; +} +.show { + display: block; +} +.invisible { + visibility: hidden; +} diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/style/bootstrap-classic.css b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/style/bootstrap-classic.css new file mode 100644 index 00000000..bb40c85f --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/style/bootstrap-classic.css @@ -0,0 +1,4983 @@ +/*! + * Bootstrap v2.0.4 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +a:hover, +a:active { + outline: 0; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} + +#map_canvas img { + max-width: none; +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} + +button, +input { + *overflow: visible; + line-height: normal; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 28px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 18px; + color: #333333; + background-color: #ffffff; +} + +a { + color: #0088cc; + text-decoration: none; +} + +a:hover { + color: #005580; + text-decoration: underline; +} + +.row { + margin-left: -20px; + *zoom: 1; +} + +.row:before, +.row:after { + display: table; + content: ""; +} + +.row:after { + clear: both; +} + +[class*="span"] { + float: left; + margin-left: 20px; +} + +.container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.span12 { + width: 940px; +} + +.span11 { + width: 860px; +} + +.span10 { + width: 780px; +} + +.span9 { + width: 700px; +} + +.span8 { + width: 620px; +} + +.span7 { + width: 540px; +} + +.span6 { + width: 460px; +} + +.span5 { + width: 380px; +} + +.span4 { + width: 300px; +} + +.span3 { + width: 220px; +} + +.span2 { + width: 140px; +} + +.span1 { + width: 60px; +} + +.offset12 { + margin-left: 980px; +} + +.offset11 { + margin-left: 900px; +} + +.offset10 { + margin-left: 820px; +} + +.offset9 { + margin-left: 740px; +} + +.offset8 { + margin-left: 660px; +} + +.offset7 { + margin-left: 580px; +} + +.offset6 { + margin-left: 500px; +} + +.offset5 { + margin-left: 420px; +} + +.offset4 { + margin-left: 340px; +} + +.offset3 { + margin-left: 260px; +} + +.offset2 { + margin-left: 180px; +} + +.offset1 { + margin-left: 100px; +} + +.row-fluid { + width: 100%; + *zoom: 1; +} + +.row-fluid:before, +.row-fluid:after { + display: table; + content: ""; +} + +.row-fluid:after { + clear: both; +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 28px; + margin-left: 2.127659574%; + *margin-left: 2.0744680846382977%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} + +.row-fluid .span12 { + width: 99.99999998999999%; + *width: 99.94680850063828%; +} + +.row-fluid .span11 { + width: 91.489361693%; + *width: 91.4361702036383%; +} + +.row-fluid .span10 { + width: 82.97872339599999%; + *width: 82.92553190663828%; +} + +.row-fluid .span9 { + width: 74.468085099%; + *width: 74.4148936096383%; +} + +.row-fluid .span8 { + width: 65.95744680199999%; + *width: 65.90425531263828%; +} + +.row-fluid .span7 { + width: 57.446808505%; + *width: 57.3936170156383%; +} + +.row-fluid .span6 { + width: 48.93617020799999%; + *width: 48.88297871863829%; +} + +.row-fluid .span5 { + width: 40.425531911%; + *width: 40.3723404216383%; +} + +.row-fluid .span4 { + width: 31.914893614%; + *width: 31.8617021246383%; +} + +.row-fluid .span3 { + width: 23.404255317%; + *width: 23.3510638276383%; +} + +.row-fluid .span2 { + width: 14.89361702%; + *width: 14.8404255306383%; +} + +.row-fluid .span1 { + width: 6.382978723%; + *width: 6.329787233638298%; +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} + +.container:before, +.container:after { + display: table; + content: ""; +} + +.container:after { + clear: both; +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} + +.container-fluid:before, +.container-fluid:after { + display: table; + content: ""; +} + +.container-fluid:after { + clear: both; +} + +p { + margin: 0 0 9px; +} + +p small { + font-size: 11px; + color: #999999; +} + +.lead { + margin-bottom: 18px; + font-size: 20px; + font-weight: 200; + line-height: 27px; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + font-family: inherit; + font-weight: bold; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + color: #999999; +} + +h1 { + font-size: 30px; + line-height: 36px; +} + +h1 small { + font-size: 18px; +} + +h2 { + font-size: 24px; + line-height: 36px; +} + +h2 small { + font-size: 18px; +} + +h3 { + font-size: 18px; + line-height: 27px; +} + +h3 small { + font-size: 14px; +} + +h4, +h5, +h6 { + line-height: 18px; +} + +h4 { + font-size: 14px; +} + +h4 small { + font-size: 12px; +} + +h5 { + font-size: 12px; +} + +h6 { + font-size: 11px; + color: #999999; + text-transform: uppercase; +} + +.page-header { + padding-bottom: 17px; + margin: 18px 0; + border-bottom: 1px solid #eeeeee; +} + +.page-header h1 { + line-height: 1; +} + +ul, +ol { + padding: 0; + margin: 0 0 9px 25px; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +ul { + list-style: disc; +} + +ol { + list-style: decimal; +} + +li { + line-height: 18px; +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} + +dl { + margin-bottom: 18px; +} + +dt, +dd { + line-height: 18px; +} + +dt { + font-weight: bold; + line-height: 17px; +} + +dd { + margin-left: 9px; +} + +.dl-horizontal dt { + float: left; + width: 120px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dl-horizontal dd { + margin-left: 130px; +} + +hr { + margin: 18px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +.muted { + color: #999999; +} + +abbr[title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 18px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + margin-bottom: 0; + font-size: 16px; + font-weight: 300; + line-height: 22.5px; +} + +blockquote small { + display: block; + line-height: 18px; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 18px; + font-style: normal; + line-height: 18px; +} + +small { + font-size: 100%; +} + +cite { + font-style: normal; +} + +code, +pre { + padding: 0 3px 2px; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +code { + padding: 2px 4px; + color: #d14; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + display: block; + padding: 8.5px; + margin: 0 0 9px; + font-size: 12.025px; + line-height: 18px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 18px; +} + +pre code { + padding: 0; + color: inherit; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +form { + margin: 0 0 18px; +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 27px; + font-size: 19.5px; + line-height: 36px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +legend small { + font-size: 13.5px; + color: #999999; +} + +label, +input, +button, +select, +textarea { + font-size: 13px; + font-weight: normal; + line-height: 18px; +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +label { + display: block; + margin-bottom: 5px; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 18px; + padding: 4px; + margin-bottom: 9px; + font-size: 13px; + line-height: 18px; + color: #555555; +} + +input, +textarea { + width: 210px; +} + +textarea { + height: auto; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); +} + +input[type="radio"], +input[type="checkbox"] { + margin: 3px 0; + *margin-top: 0; + /* IE7 */ + + line-height: normal; + cursor: pointer; +} + +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +select, +input[type="file"] { + height: 28px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 28px; +} + +select { + width: 220px; + border: 1px solid #bbb; +} + +select[multiple], +select[size] { + height: auto; +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.radio, +.checkbox { + min-height: 18px; + padding-left: 18px; +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -18px; +} + +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} + +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} + +.input-mini { + width: 60px; +} + +.input-small { + width: 90px; +} + +.input-medium { + width: 150px; +} + +.input-large { + width: 210px; +} + +.input-xlarge { + width: 270px; +} + +.input-xxlarge { + width: 530px; +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} + +input, +textarea, +.uneditable-input { + margin-left: 0; +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 930px; +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 850px; +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 770px; +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 690px; +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 610px; +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 530px; +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 450px; +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 370px; +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 290px; +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 210px; +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 130px; +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 50px; +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; + border-color: #ddd; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} + +.control-group.warning > label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; + border-color: #c09853; +} + +.control-group.warning .checkbox:focus, +.control-group.warning .radio:focus, +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: 0 0 6px #dbc59e; + -moz-box-shadow: 0 0 6px #dbc59e; + box-shadow: 0 0 6px #dbc59e; +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.control-group.error > label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; + border-color: #b94a48; +} + +.control-group.error .checkbox:focus, +.control-group.error .radio:focus, +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: 0 0 6px #d59392; + -moz-box-shadow: 0 0 6px #d59392; + box-shadow: 0 0 6px #d59392; +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.control-group.success > label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; + border-color: #468847; +} + +.control-group.success .checkbox:focus, +.control-group.success .radio:focus, +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: 0 0 6px #7aba7b; + -moz-box-shadow: 0 0 6px #7aba7b; + box-shadow: 0 0 6px #7aba7b; +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +input:focus:required:invalid, +textarea:focus:required:invalid, +select:focus:required:invalid { + color: #b94a48; + border-color: #ee5f5b; +} + +input:focus:required:invalid:focus, +textarea:focus:required:invalid:focus, +select:focus:required:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} + +.form-actions { + padding: 17px 20px 18px; + margin-top: 18px; + margin-bottom: 18px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} + +.form-actions:before, +.form-actions:after { + display: table; + content: ""; +} + +.form-actions:after { + clear: both; +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; + cursor: not-allowed; + background-color: #ffffff; + border-color: #eee; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +:-moz-placeholder { + color: #999999; +} + +:-ms-input-placeholder { + color: #999999; +} + +::-webkit-input-placeholder { + color: #999999; +} + +.help-block, +.help-inline { + color: #555555; +} + +.help-block { + display: block; + margin-bottom: 9px; +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1; +} + +.input-prepend, +.input-append { + margin-bottom: 5px; +} + +.input-prepend input, +.input-append input, +.input-prepend select, +.input-append select, +.input-prepend .uneditable-input, +.input-append .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: middle; + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.input-prepend input:focus, +.input-append input:focus, +.input-prepend select:focus, +.input-append select:focus, +.input-prepend .uneditable-input:focus, +.input-append .uneditable-input:focus { + z-index: 2; +} + +.input-prepend .uneditable-input, +.input-append .uneditable-input { + border-left-color: #ccc; +} + +.input-prepend .add-on, +.input-append .add-on { + display: inline-block; + width: auto; + height: 18px; + min-width: 16px; + padding: 4px 5px; + font-weight: normal; + line-height: 18px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + vertical-align: middle; + background-color: #eeeeee; + border: 1px solid #ccc; +} + +.input-prepend .add-on, +.input-append .add-on, +.input-prepend .btn, +.input-append .btn { + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend .active, +.input-append .active { + background-color: #a9dba9; + border-color: #46a546; +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.input-append .uneditable-input { + border-right-color: #ccc; + border-left-color: #eee; +} + +.input-append .add-on:last-child, +.input-append .btn:last-child { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 14px; + -moz-border-radius: 14px; + border-radius: 14px; +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + *zoom: 1; +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} + +.form-search label, +.form-inline label { + display: inline-block; +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} + +.control-group { + margin-bottom: 9px; +} + +legend + .control-group { + margin-top: 18px; + -webkit-margin-top-collapse: separate; +} + +.form-horizontal .control-group { + margin-bottom: 18px; + *zoom: 1; +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + content: ""; +} + +.form-horizontal .control-group:after { + clear: both; +} + +.form-horizontal .control-label { + float: left; + width: 140px; + padding-top: 5px; + text-align: right; +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 160px; + *margin-left: 0; +} + +.form-horizontal .controls:first-child { + *padding-left: 160px; +} + +.form-horizontal .help-block { + margin-top: 9px; + margin-bottom: 0; +} + +.form-horizontal .form-actions { + padding-left: 160px; +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} + +.table { + width: 100%; + margin-bottom: 18px; +} + +.table th, +.table td { + padding: 8px; + line-height: 18px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table th { + font-weight: bold; +} + +.table thead th { + vertical-align: bottom; +} + +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} + +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapsed; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} + +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} + +.table-bordered thead:first-child tr:first-child th:first-child, +.table-bordered tbody:first-child tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered thead:first-child tr:first-child th:last-child, +.table-bordered tbody:first-child tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-bordered thead:last-child tr:last-child th:first-child, +.table-bordered tbody:last-child tr:last-child td:first-child { + -webkit-border-radius: 0 0 0 4px; + -moz-border-radius: 0 0 0 4px; + border-radius: 0 0 0 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.table-bordered thead:last-child tr:last-child th:last-child, +.table-bordered tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} + +.table-striped tbody tr:nth-child(odd) td, +.table-striped tbody tr:nth-child(odd) th { + background-color: #f9f9f9; +} + +.table tbody tr:hover td, +.table tbody tr:hover th { + background-color: #f5f5f5; +} + +table .span1 { + float: none; + width: 44px; + margin-left: 0; +} + +table .span2 { + float: none; + width: 124px; + margin-left: 0; +} + +table .span3 { + float: none; + width: 204px; + margin-left: 0; +} + +table .span4 { + float: none; + width: 284px; + margin-left: 0; +} + +table .span5 { + float: none; + width: 364px; + margin-left: 0; +} + +table .span6 { + float: none; + width: 444px; + margin-left: 0; +} + +table .span7 { + float: none; + width: 524px; + margin-left: 0; +} + +table .span8 { + float: none; + width: 604px; + margin-left: 0; +} + +table .span9 { + float: none; + width: 684px; + margin-left: 0; +} + +table .span10 { + float: none; + width: 764px; + margin-left: 0; +} + +table .span11 { + float: none; + width: 844px; + margin-left: 0; +} + +table .span12 { + float: none; + width: 924px; + margin-left: 0; +} + +table .span13 { + float: none; + width: 1004px; + margin-left: 0; +} + +table .span14 { + float: none; + width: 1084px; + margin-left: 0; +} + +table .span15 { + float: none; + width: 1164px; + margin-left: 0; +} + +table .span16 { + float: none; + width: 1244px; + margin-left: 0; +} + +table .span17 { + float: none; + width: 1324px; + margin-left: 0; +} + +table .span18 { + float: none; + width: 1404px; + margin-left: 0; +} + +table .span19 { + float: none; + width: 1484px; + margin-left: 0; +} + +table .span20 { + float: none; + width: 1564px; + margin-left: 0; +} + +table .span21 { + float: none; + width: 1644px; + margin-left: 0; +} + +table .span22 { + float: none; + width: 1724px; + margin-left: 0; +} + +table .span23 { + float: none; + width: 1804px; + margin-left: 0; +} + +table .span24 { + float: none; + width: 1884px; + margin-left: 0; +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} + +[class^="icon-"]:last-child, +[class*=" icon-"]:last-child { + *margin-left: 0; +} + +.icon-white { + background-image: url("../img/glyphicons-halflings-white.png"); +} + +.icon-glass { + background-position: 0 0; +} + +.icon-music { + background-position: -24px 0; +} + +.icon-search { + background-position: -48px 0; +} + +.icon-envelope { + background-position: -72px 0; +} + +.icon-heart { + background-position: -96px 0; +} + +.icon-star { + background-position: -120px 0; +} + +.icon-star-empty { + background-position: -144px 0; +} + +.icon-user { + background-position: -168px 0; +} + +.icon-film { + background-position: -192px 0; +} + +.icon-th-large { + background-position: -216px 0; +} + +.icon-th { + background-position: -240px 0; +} + +.icon-th-list { + background-position: -264px 0; +} + +.icon-ok { + background-position: -288px 0; +} + +.icon-remove { + background-position: -312px 0; +} + +.icon-zoom-in { + background-position: -336px 0; +} + +.icon-zoom-out { + background-position: -360px 0; +} + +.icon-off { + background-position: -384px 0; +} + +.icon-signal { + background-position: -408px 0; +} + +.icon-cog { + background-position: -432px 0; +} + +.icon-trash { + background-position: -456px 0; +} + +.icon-home { + background-position: 0 -24px; +} + +.icon-file { + background-position: -24px -24px; +} + +.icon-time { + background-position: -48px -24px; +} + +.icon-road { + background-position: -72px -24px; +} + +.icon-download-alt { + background-position: -96px -24px; +} + +.icon-download { + background-position: -120px -24px; +} + +.icon-upload { + background-position: -144px -24px; +} + +.icon-inbox { + background-position: -168px -24px; +} + +.icon-play-circle { + background-position: -192px -24px; +} + +.icon-repeat { + background-position: -216px -24px; +} + +.icon-refresh { + background-position: -240px -24px; +} + +.icon-list-alt { + background-position: -264px -24px; +} + +.icon-lock { + background-position: -287px -24px; +} + +.icon-flag { + background-position: -312px -24px; +} + +.icon-headphones { + background-position: -336px -24px; +} + +.icon-volume-off { + background-position: -360px -24px; +} + +.icon-volume-down { + background-position: -384px -24px; +} + +.icon-volume-up { + background-position: -408px -24px; +} + +.icon-qrcode { + background-position: -432px -24px; +} + +.icon-barcode { + background-position: -456px -24px; +} + +.icon-tag { + background-position: 0 -48px; +} + +.icon-tags { + background-position: -25px -48px; +} + +.icon-book { + background-position: -48px -48px; +} + +.icon-bookmark { + background-position: -72px -48px; +} + +.icon-print { + background-position: -96px -48px; +} + +.icon-camera { + background-position: -120px -48px; +} + +.icon-font { + background-position: -144px -48px; +} + +.icon-bold { + background-position: -167px -48px; +} + +.icon-italic { + background-position: -192px -48px; +} + +.icon-text-height { + background-position: -216px -48px; +} + +.icon-text-width { + background-position: -240px -48px; +} + +.icon-align-left { + background-position: -264px -48px; +} + +.icon-align-center { + background-position: -288px -48px; +} + +.icon-align-right { + background-position: -312px -48px; +} + +.icon-align-justify { + background-position: -336px -48px; +} + +.icon-list { + background-position: -360px -48px; +} + +.icon-indent-left { + background-position: -384px -48px; +} + +.icon-indent-right { + background-position: -408px -48px; +} + +.icon-facetime-video { + background-position: -432px -48px; +} + +.icon-picture { + background-position: -456px -48px; +} + +.icon-pencil { + background-position: 0 -72px; +} + +.icon-map-marker { + background-position: -24px -72px; +} + +.icon-adjust { + background-position: -48px -72px; +} + +.icon-tint { + background-position: -72px -72px; +} + +.icon-edit { + background-position: -96px -72px; +} + +.icon-share { + background-position: -120px -72px; +} + +.icon-check { + background-position: -144px -72px; +} + +.icon-move { + background-position: -168px -72px; +} + +.icon-step-backward { + background-position: -192px -72px; +} + +.icon-fast-backward { + background-position: -216px -72px; +} + +.icon-backward { + background-position: -240px -72px; +} + +.icon-play { + background-position: -264px -72px; +} + +.icon-pause { + background-position: -288px -72px; +} + +.icon-stop { + background-position: -312px -72px; +} + +.icon-forward { + background-position: -336px -72px; +} + +.icon-fast-forward { + background-position: -360px -72px; +} + +.icon-step-forward { + background-position: -384px -72px; +} + +.icon-eject { + background-position: -408px -72px; +} + +.icon-chevron-left { + background-position: -432px -72px; +} + +.icon-chevron-right { + background-position: -456px -72px; +} + +.icon-plus-sign { + background-position: 0 -96px; +} + +.icon-minus-sign { + background-position: -24px -96px; +} + +.icon-remove-sign { + background-position: -48px -96px; +} + +.icon-ok-sign { + background-position: -72px -96px; +} + +.icon-question-sign { + background-position: -96px -96px; +} + +.icon-info-sign { + background-position: -120px -96px; +} + +.icon-screenshot { + background-position: -144px -96px; +} + +.icon-remove-circle { + background-position: -168px -96px; +} + +.icon-ok-circle { + background-position: -192px -96px; +} + +.icon-ban-circle { + background-position: -216px -96px; +} + +.icon-arrow-left { + background-position: -240px -96px; +} + +.icon-arrow-right { + background-position: -264px -96px; +} + +.icon-arrow-up { + background-position: -289px -96px; +} + +.icon-arrow-down { + background-position: -312px -96px; +} + +.icon-share-alt { + background-position: -336px -96px; +} + +.icon-resize-full { + background-position: -360px -96px; +} + +.icon-resize-small { + background-position: -384px -96px; +} + +.icon-plus { + background-position: -408px -96px; +} + +.icon-minus { + background-position: -433px -96px; +} + +.icon-asterisk { + background-position: -456px -96px; +} + +.icon-exclamation-sign { + background-position: 0 -120px; +} + +.icon-gift { + background-position: -24px -120px; +} + +.icon-leaf { + background-position: -48px -120px; +} + +.icon-fire { + background-position: -72px -120px; +} + +.icon-eye-open { + background-position: -96px -120px; +} + +.icon-eye-close { + background-position: -120px -120px; +} + +.icon-warning-sign { + background-position: -144px -120px; +} + +.icon-plane { + background-position: -168px -120px; +} + +.icon-calendar { + background-position: -192px -120px; +} + +.icon-random { + background-position: -216px -120px; +} + +.icon-comment { + background-position: -240px -120px; +} + +.icon-magnet { + background-position: -264px -120px; +} + +.icon-chevron-up { + background-position: -288px -120px; +} + +.icon-chevron-down { + background-position: -313px -119px; +} + +.icon-retweet { + background-position: -336px -120px; +} + +.icon-shopping-cart { + background-position: -360px -120px; +} + +.icon-folder-close { + background-position: -384px -120px; +} + +.icon-folder-open { + background-position: -408px -120px; +} + +.icon-resize-vertical { + background-position: -432px -119px; +} + +.icon-resize-horizontal { + background-position: -456px -118px; +} + +.icon-hdd { + background-position: 0 -144px; +} + +.icon-bullhorn { + background-position: -24px -144px; +} + +.icon-bell { + background-position: -48px -144px; +} + +.icon-certificate { + background-position: -72px -144px; +} + +.icon-thumbs-up { + background-position: -96px -144px; +} + +.icon-thumbs-down { + background-position: -120px -144px; +} + +.icon-hand-right { + background-position: -144px -144px; +} + +.icon-hand-left { + background-position: -168px -144px; +} + +.icon-hand-up { + background-position: -192px -144px; +} + +.icon-hand-down { + background-position: -216px -144px; +} + +.icon-circle-arrow-right { + background-position: -240px -144px; +} + +.icon-circle-arrow-left { + background-position: -264px -144px; +} + +.icon-circle-arrow-up { + background-position: -288px -144px; +} + +.icon-circle-arrow-down { + background-position: -312px -144px; +} + +.icon-globe { + background-position: -336px -144px; +} + +.icon-wrench { + background-position: -360px -144px; +} + +.icon-tasks { + background-position: -384px -144px; +} + +.icon-filter { + background-position: -408px -144px; +} + +.icon-briefcase { + background-position: -432px -144px; +} + +.icon-fullscreen { + background-position: -456px -144px; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + *margin-bottom: -3px; +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; + opacity: 0.3; + filter: alpha(opacity=30); +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} + +.dropdown:hover .caret, +.open .caret { + opacity: 1; + filter: alpha(opacity=100); +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 4px 0; + margin: 1px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 8px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.dropdown-menu a { + display: block; + padding: 3px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu li > a:hover, +.dropdown-menu .active > a, +.dropdown-menu .active > a:hover { + color: #ffffff; + text-decoration: none; + background-color: #0088cc; +} + +.open { + *z-index: 1000; +} + +.open > .dropdown-menu { + display: block; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: "\2191"; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +.typeahead { + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #eee; + border: 1px solid rgba(0, 0, 0, 0.05); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -ms-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -ms-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.collapse.in { + height: auto; +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 18px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 10px 4px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 13px; + line-height: 18px; + *line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(top, #ffffff, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #cccccc; + *border: 0; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn:hover, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + background-color: #e6e6e6; + *background-color: #d9d9d9; +} + +.btn:active, +.btn.active { + background-color: #cccccc \9; +} + +.btn:first-child { + *margin-left: 0; +} + +.btn:hover { + color: #333333; + text-decoration: none; + background-color: #e6e6e6; + *background-color: #d9d9d9; + /* Buttons in IE7 don't get borders, so darken on hover */ + + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -ms-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn.active, +.btn:active { + background-color: #e6e6e6; + background-color: #d9d9d9 \9; + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-color: #e6e6e6; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-large { + padding: 9px 14px; + font-size: 15px; + line-height: normal; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.btn-large [class^="icon-"] { + margin-top: 1px; +} + +.btn-small { + padding: 5px 9px; + font-size: 11px; + line-height: 16px; +} + +.btn-small [class^="icon-"] { + margin-top: -1px; +} + +.btn-mini { + padding: 2px 6px; + font-size: 11px; + line-height: 14px; +} + +.btn-primary, +.btn-primary:hover, +.btn-warning, +.btn-warning:hover, +.btn-danger, +.btn-danger:hover, +.btn-success, +.btn-success:hover, +.btn-info, +.btn-info:hover, +.btn-inverse, +.btn-inverse:hover { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} + +.btn { + border-color: #ccc; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} + +.btn-primary { + background-color: #0074cc; + *background-color: #0055cc; + background-image: -ms-linear-gradient(top, #0088cc, #0055cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0055cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0055cc); + background-image: -o-linear-gradient(top, #0088cc, #0055cc); + background-image: -moz-linear-gradient(top, #0088cc, #0055cc); + background-image: linear-gradient(top, #0088cc, #0055cc); + background-repeat: repeat-x; + border-color: #0055cc #0055cc #003580; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc', endColorstr='#0055cc', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); +} + +.btn-primary:hover, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + background-color: #0055cc; + *background-color: #004ab3; +} + +.btn-primary:active, +.btn-primary.active { + background-color: #004099 \9; +} + +.btn-warning { + background-color: #faa732; + *background-color: #f89406; + background-image: -ms-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(top, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); +} + +.btn-warning:hover, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + background-color: #f89406; + *background-color: #df8505; +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} + +.btn-danger { + background-color: #da4f49; + *background-color: #bd362f; + background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(top, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); +} + +.btn-danger:hover, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + background-color: #bd362f; + *background-color: #a9302a; +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} + +.btn-success { + background-color: #5bb75b; + *background-color: #51a351; + background-image: -ms-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(top, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); +} + +.btn-success:hover, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + background-color: #51a351; + *background-color: #499249; +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} + +.btn-info { + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(top, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); +} + +.btn-info:hover, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + background-color: #2f96b4; + *background-color: #2a85a0; +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} + +.btn-inverse { + background-color: #414141; + *background-color: #222222; + background-image: -ms-linear-gradient(top, #555555, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#222222)); + background-image: -webkit-linear-gradient(top, #555555, #222222); + background-image: -o-linear-gradient(top, #555555, #222222); + background-image: -moz-linear-gradient(top, #555555, #222222); + background-image: linear-gradient(top, #555555, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#555555', endColorstr='#222222', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); +} + +.btn-inverse:hover, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + background-color: #222222; + *background-color: #151515; +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} + +button.btn, +input[type="submit"].btn { + *padding-top: 2px; + *padding-bottom: 2px; +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} + +.btn-group { + position: relative; + *margin-left: .3em; + *zoom: 1; +} + +.btn-group:before, +.btn-group:after { + display: table; + content: ""; +} + +.btn-group:after { + clear: both; +} + +.btn-group:first-child { + *margin-left: 0; +} + +.btn-group + .btn-group { + margin-left: 5px; +} + +.btn-toolbar { + margin-top: 9px; + margin-bottom: 9px; +} + +.btn-toolbar .btn-group { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group > .btn { + position: relative; + float: left; + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .dropdown-toggle { + *padding-top: 4px; + padding-right: 8px; + *padding-bottom: 4px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group > .btn-mini.dropdown-toggle { + padding-right: 5px; + padding-left: 5px; +} + +.btn-group > .btn-small.dropdown-toggle { + *padding-top: 4px; + *padding-bottom: 4px; +} + +.btn-group > .btn-large.dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0055cc; +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} + +.btn .caret { + margin-top: 7px; + margin-left: 0; +} + +.btn:hover .caret, +.open.btn-group .caret { + opacity: 1; + filter: alpha(opacity=100); +} + +.btn-mini .caret { + margin-top: 5px; +} + +.btn-small .caret { + margin-top: 6px; +} + +.btn-large .caret { + margin-top: 6px; + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.dropup .btn-large .caret { + border-top: 0; + border-bottom: 5px solid #000000; +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 0.75; + filter: alpha(opacity=75); +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 18px; + color: #c09853; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.alert-heading { + color: inherit; +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 18px; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} + +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} + +.alert-block p + p { + margin-top: 5px; +} + +.nav { + margin-bottom: 18px; + margin-left: 0; + list-style: none; +} + +.nav > li > a { + display: block; +} + +.nav > li > a:hover { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > .pull-right { + float: right; +} + +.nav .nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 18px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} + +.nav li + .nav-header { + margin-top: 9px; +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0; +} + +.nav-list > li > a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.nav-list > li > a { + padding: 3px 15px; +} + +.nav-list > .active > a, +.nav-list > .active > a:hover { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} + +.nav-list [class^="icon-"] { + margin-right: 2px; +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 8px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.nav-tabs, +.nav-pills { + *zoom: 1; +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + content: ""; +} + +.nav-tabs:after, +.nav-pills:after { + clear: both; +} + +.nav-tabs > li, +.nav-pills > li { + float: left; +} + +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} + +.nav-tabs { + border-bottom: 1px solid #ddd; +} + +.nav-tabs > li { + margin-bottom: -1px; +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 18px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.nav-pills > .active > a, +.nav-pills > .active > a:hover { + color: #ffffff; + background-color: #0088cc; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li > a { + margin-right: 0; +} + +.nav-tabs.nav-stacked { + border-bottom: 0; +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.nav-tabs.nav-stacked > li > a:hover { + z-index: 2; + border-color: #ddd; +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.nav-tabs .dropdown-toggle .caret, +.nav-pills .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #0088cc; + border-bottom-color: #0088cc; +} + +.nav-tabs .dropdown-toggle:hover .caret, +.nav-pills .dropdown-toggle:hover .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} + +.nav-tabs .active .dropdown-toggle .caret, +.nav-pills .active .dropdown-toggle .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.nav > .dropdown.active > a:hover { + color: #000000; + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} + +.tabs-stacked .open > a:hover { + border-color: #999999; +} + +.tabbable { + *zoom: 1; +} + +.tabbable:before, +.tabbable:after { + display: table; + content: ""; +} + +.tabbable:after { + clear: both; +} + +.tab-content { + overflow: auto; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.tabs-below > .nav-tabs > li > a:hover { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover { + border-color: transparent #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} + +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.tabs-left > .nav-tabs > li > a:hover { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.tabs-right > .nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 18px; + overflow: visible; +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #2c2c2c; + background-image: -moz-linear-gradient(top, #333333, #222222); + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); +} + +.navbar .container { + width: auto; +} + +.nav-collapse.collapse { + height: auto; +} + +.navbar { + color: #999999; +} + +.navbar .brand:hover { + text-decoration: none; +} + +.navbar .brand { + display: block; + float: left; + padding: 8px 20px 12px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + line-height: 1; + color: #999999; +} + +.navbar .navbar-text { + margin-bottom: 0; + line-height: 40px; +} + +.navbar .navbar-link { + color: #999999; +} + +.navbar .navbar-link:hover { + color: #ffffff; +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} + +.navbar .btn-group .btn { + margin: 0; +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} + +.navbar-form:before, +.navbar-form:after { + display: table; + content: ""; +} + +.navbar-form:after { + clear: both; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} + +.navbar-form input, +.navbar-form select { + display: inline-block; + margin-bottom: 0; +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 6px; + white-space: nowrap; +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} + +.navbar-search { + position: relative; + float: left; + margin-top: 6px; + margin-bottom: 0; +} + +.navbar-search .search-query { + padding: 4px 9px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + color: #ffffff; + background-color: #626262; + border: 1px solid #151515; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; +} + +.navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} + +.navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} + +.navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} + +.navbar-search .search-query:focus, +.navbar-search .search-query.focused { + padding: 5px 10px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.navbar-fixed-top { + top: 0; +} + +.navbar-fixed-bottom { + bottom: 0; +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} + +.navbar .nav.pull-right { + float: right; +} + +.navbar .nav > li { + display: block; + float: left; +} + +.navbar .nav > li > a { + float: none; + padding: 9px 10px 11px; + line-height: 19px; + color: #999999; + text-decoration: none; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar .btn { + display: inline-block; + padding: 4px 10px 4px; + margin: 5px 5px 6px; + line-height: 18px; +} + +.navbar .btn-group { + padding: 5px 5px 6px; + margin: 0; +} + +.navbar .nav > li > a:hover { + color: #ffffff; + text-decoration: none; + background-color: transparent; +} + +.navbar .nav .active > a, +.navbar .nav .active > a:hover { + color: #ffffff; + text-decoration: none; + background-color: #222222; +} + +.navbar .divider-vertical { + width: 1px; + height: 40px; + margin: 0 9px; + overflow: hidden; + background-color: #222222; + border-right: 1px solid #333333; +} + +.navbar .nav.pull-right { + margin-right: 0; + margin-left: 10px; +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + background-color: #2c2c2c; + *background-color: #222222; + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + background-image: -moz-linear-gradient(top, #333333, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); + filter: progid:dximagetransform.microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + background-color: #222222; + *background-color: #151515; +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #080808 \9; +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} + +.navbar .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.navbar .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-left: 6px solid transparent; + content: ''; +} + +.navbar-fixed-bottom .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.navbar-fixed-bottom .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.navbar .nav li.dropdown .dropdown-toggle .caret, +.navbar .nav li.dropdown.open .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar .nav li.dropdown.active .caret { + opacity: 1; + filter: alpha(opacity=100); +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + background-color: transparent; +} + +.navbar .nav li.dropdown.active > .dropdown-toggle:hover { + color: #ffffff; +} + +.navbar .pull-right .dropdown-menu, +.navbar .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right .dropdown-menu:before, +.navbar .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right .dropdown-menu:after, +.navbar .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.breadcrumb { + padding: 7px 14px; + margin: 0 0 18px; + list-style: none; + background-color: #fbfbfb; + background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); + background-image: linear-gradient(top, #ffffff, #f5f5f5); + background-repeat: repeat-x; + border: 1px solid #ddd; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.breadcrumb li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #ffffff; + *zoom: 1; +} + +.breadcrumb .divider { + padding: 0 5px; + color: #999999; +} + +.breadcrumb .active a { + color: #333333; +} + +.pagination { + height: 36px; + margin: 18px 0; +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.pagination li { + display: inline; +} + +.pagination a { + float: left; + padding: 0 14px; + line-height: 34px; + text-decoration: none; + border: 1px solid #ddd; + border-left-width: 0; +} + +.pagination a:hover, +.pagination .active a { + background-color: #f5f5f5; +} + +.pagination .active a { + color: #999999; + cursor: default; +} + +.pagination .disabled span, +.pagination .disabled a, +.pagination .disabled a:hover { + color: #999999; + cursor: default; + background-color: transparent; +} + +.pagination li:first-child a { + border-left-width: 1px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.pagination li:last-child a { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.pagination-centered { + text-align: center; +} + +.pagination-right { + text-align: right; +} + +.pager { + margin-bottom: 18px; + margin-left: 0; + text-align: center; + list-style: none; + *zoom: 1; +} + +.pager:before, +.pager:after { + display: table; + content: ""; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager a { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.pager a:hover { + text-decoration: none; + background-color: #f5f5f5; +} + +.pager .next a { + float: right; +} + +.pager .previous a { + float: left; +} + +.pager .disabled a, +.pager .disabled a:hover { + color: #999999; + cursor: default; + background-color: #fff; +} + +.modal-open .dropdown-menu { + z-index: 2050; +} + +.modal-open .dropdown.open { + *z-index: 2050; +} + +.modal-open .popover { + z-index: 2060; +} + +.modal-open .tooltip { + z-index: 2070; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 1050; + width: 560px; + margin: -250px 0 0 -280px; + overflow: auto; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -ms-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 50%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-body { + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.tooltip { + position: absolute; + z-index: 1020; + display: block; + padding: 5px; + font-size: 11px; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.tooltip.top { + margin-top: -2px; +} + +.tooltip.right { + margin-left: 2px; +} + +.tooltip.bottom { + margin-top: 2px; +} + +.tooltip.left { + margin-left: -2px; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top: 5px solid #000000; + border-right: 5px solid transparent; + border-left: 5px solid transparent; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; + border-left: 5px solid transparent; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-right: 5px solid #000000; + border-bottom: 5px solid transparent; +} + +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + padding: 5px; +} + +.popover.top { + margin-top: -5px; +} + +.popover.right { + margin-left: 5px; +} + +.popover.bottom { + margin-top: 5px; +} + +.popover.left { + margin-left: -5px; +} + +.popover.top .arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top: 5px solid #000000; + border-right: 5px solid transparent; + border-left: 5px solid transparent; +} + +.popover.right .arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-right: 5px solid #000000; + border-bottom: 5px solid transparent; +} + +.popover.bottom .arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-right: 5px solid transparent; + border-bottom: 5px solid #000000; + border-left: 5px solid transparent; +} + +.popover.left .arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid #000000; +} + +.popover .arrow { + position: absolute; + width: 0; + height: 0; +} + +.popover-inner { + width: 280px; + padding: 3px; + overflow: hidden; + background: #000000; + background: rgba(0, 0, 0, 0.8); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); +} + +.popover-title { + padding: 9px 15px; + line-height: 1; + background-color: #f5f5f5; + border-bottom: 1px solid #eee; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; +} + +.popover-content { + padding: 14px; + background-color: #ffffff; + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.popover-content p, +.popover-content ul, +.popover-content ol { + margin-bottom: 0; +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} + +.thumbnails:before, +.thumbnails:after { + display: table; + content: ""; +} + +.thumbnails:after { + clear: both; +} + +.row-fluid .thumbnails { + margin-left: 0; +} + +.thumbnails > li { + float: left; + margin-bottom: 18px; + margin-left: 20px; +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 1; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); +} + +a.thumbnail:hover { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; +} + +.label, +.badge { + font-size: 10.998px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; +} + +.label { + padding: 1px 4px 2px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.badge { + padding: 1px 9px 2px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +a.label:hover, +a.badge:hover { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label-important, +.badge-important { + background-color: #b94a48; +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} + +.label-warning, +.badge-warning { + background-color: #f89406; +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} + +.label-success, +.badge-success { + background-color: #468847; +} + +.label-success[href], +.badge-success[href] { + background-color: #356635; +} + +.label-info, +.badge-info { + background-color: #3a87ad; +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} + +.label-inverse, +.badge-inverse { + background-color: #333333; +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 18px; + margin-bottom: 18px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(top, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress .bar { + width: 0; + height: 18px; + font-size: 12px; + color: #ffffff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(top, #149bdf, #0480be); + background-image: -ms-linear-gradient(top, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -ms-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-danger .bar { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); +} + +.progress-danger.progress-striped .bar { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-success .bar { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -ms-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(top, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); +} + +.progress-success.progress-striped .bar { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-info .bar { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(top, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); +} + +.progress-info.progress-striped .bar { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-warning .bar { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -ms-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(top, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); +} + +.progress-warning.progress-striped .bar { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.accordion { + margin-bottom: 18px; +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.accordion-heading { + border-bottom: 0; +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} + +.accordion-toggle { + cursor: pointer; +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} + +.carousel { + position: relative; + margin-bottom: 18px; + line-height: 1; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -ms-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel .item > img { + display: block; + line-height: 1; +} + +.carousel .active, +.carousel .next, +.carousel .prev { + display: block; +} + +.carousel .active { + left: 0; +} + +.carousel .next, +.carousel .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel .next { + left: 100%; +} + +.carousel .prev { + left: -100%; +} + +.carousel .next.left, +.carousel .prev.right { + left: 0; +} + +.carousel .active.left { + left: -100%; +} + +.carousel .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.right { + right: 15px; + left: auto; +} + +.carousel-control:hover { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 10px 15px 5px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} + +.carousel-caption h4, +.carousel-caption p { + color: #ffffff; +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit; +} + +.hero-unit p { + font-size: 18px; + font-weight: 200; + line-height: 27px; + color: inherit; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.hide { + display: none; +} + +.show { + display: block; +} + +.invisible { + visibility: hidden; +} diff --git a/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/testcase.html b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/testcase.html new file mode 100644 index 00000000..62334744 --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/Bench4QTestCase/testcase.html @@ -0,0 +1,17 @@ + + + Bench4Q Test Case + + + + + + No this one + No this one + No this one + + + + + + diff --git a/Bench4Q-Master/RecordScriptTestCase/baidu.html b/Bench4Q-Master/RecordScriptTestCase/baidu.html new file mode 100644 index 00000000..373ced8a --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/baidu.html @@ -0,0 +1,17 @@ + + + Bench4Q Test Case + + + + + + No this one + No this one + No this one + + + + + + \ No newline at end of file diff --git a/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRNotHtmlResponse.html b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRNotHtmlResponse.html new file mode 100644 index 00000000..47d8fc0d --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRNotHtmlResponse.html @@ -0,0 +1,16 @@ +HTTP/1.1 200 OK +Content-Type: text/plain; charset=utf-8 +Server: Microsoft-IIS/7.0 +CachedXSLT: true +X-AspNet-Version: 2.0.50727 +X-Powered-By: ASP.NET +Vary: Accept-Encoding +Cache-Control: private, max-age=31 +Date: Tue, 10 Dec 2013 08:40:29 GMT +Content-Length: 6 +Connection: keep-alive +Set-Cookie: agentscape-tag-devtype=desktop; Path=/ +Set-Cookie: agentscape-proc=noop; Path=/ +x-agentscape-info: c=1.0-r9869; v=3; fp=f844b0e65e9b5458; ts=1333395837 + +adnddm \ No newline at end of file diff --git a/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRNullResponseBody.html b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRNullResponseBody.html new file mode 100644 index 00000000..34fc26d7 --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRNullResponseBody.html @@ -0,0 +1,14 @@ +HTTP/1.1 200 OK +Content-Type: text/html; charset=utf-8 +Server: Microsoft-IIS/7.0 +CachedXSLT: true +X-AspNet-Version: 2.0.50727 +X-Powered-By: ASP.NET +Vary: Accept-Encoding +Cache-Control: private, max-age=31 +Date: Tue, 10 Dec 2013 08:40:29 GMT +Content-Length: 0 +Connection: keep-alive +Set-Cookie: agentscape-tag-devtype=desktop; Path=/ +Set-Cookie: agentscape-proc=noop; Path=/ +x-agentscape-info: c=1.0-r9869; v=3; fp=f844b0e65e9b5458; ts=1333395837 diff --git a/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRRequest.txt b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRRequest.txt new file mode 100644 index 00000000..3b2fea2d --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRRequest.txt @@ -0,0 +1,15 @@ +GET /phoenix.zhtml?c=188488&p=irol-homeprofile HTTP/1.1 +Host: ir.baidu.com +Connection: keep-alive +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 +Referer: http://www.baidu.com/ +Accept-Encoding: gzip,deflate,sdch +IF-MODIFIED-SINCE: Mon, 22 Mar 2010 14:14:40 GMT; old-content-length=200 +AUTHORIZATION: bearer +Accept-Language: zh-CN,zh;q=0.8 +Content-Type: multipart +Content-Length: 100 +Pragma: No-Cache +Cookie: BAIDUID=993724E1CAB01EE3D0C0AFAA99796E6A:FG=1; H_PS_PSSID=4381_1463_4212_4264_4451 + diff --git a/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRResponse.txt b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRResponse.txt new file mode 100644 index 00000000..0f78a4ba Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRResponse.txt differ diff --git a/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRResponseBody.txt b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRResponseBody.txt new file mode 100644 index 00000000..3ea009e5 Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/gzip/gzipBaiduIRResponseBody.txt differ diff --git a/Bench4Q-Master/RecordScriptTestCase/gzipBaiduRequestHeader.txt b/Bench4Q-Master/RecordScriptTestCase/gzipBaiduRequestHeader.txt new file mode 100644 index 00000000..91e99ea6 --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/gzipBaiduRequestHeader.txt @@ -0,0 +1,10 @@ +GET / HTTP/1.1 +Host: www.baidu.com +Connection: keep-alive +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 +DNT: 1 +Accept-Encoding: gzip,deflate,sdch +Accept-Language: en,zh-CN;q=0.8,zh;q=0.6 +Cookie: BAIDUID=1D43A956BCED0A81B8340058134CD2F6:FG=1; BDUSS=EJMRWZ2eklMaERoQ344em5RZ2EyTVh0UjRDcWpiRmhnMjRlLTZnR3NZajBOS0JTQVFBQUFBJCQAAAAAAAAAAAEAAAA2JuwxZmVuZ3l1bjIwMTIzOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSneFL0p3hSN; Hm_lvt_9f14aaa038bbba8b12ec2a4a3e51d254=1384429678; H_PS_PSSID=3784_4199_1432_4421_4414_4211_4264_4450_4503; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0 + diff --git a/Bench4Q-Master/RecordScriptTestCase/gzipBaiduResponse.txt b/Bench4Q-Master/RecordScriptTestCase/gzipBaiduResponse.txt new file mode 100644 index 00000000..ab5dd0ff Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/gzipBaiduResponse.txt differ diff --git a/Bench4Q-Master/RecordScriptTestCase/gzipBaiduResponseBody.txt b/Bench4Q-Master/RecordScriptTestCase/gzipBaiduResponseBody.txt new file mode 100644 index 00000000..219f979a Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/gzipBaiduResponseBody.txt differ diff --git a/Bench4Q-Master/RecordScriptTestCase/gzipChunkedGoogleResponse.txt b/Bench4Q-Master/RecordScriptTestCase/gzipChunkedGoogleResponse.txt new file mode 100644 index 00000000..99062457 Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/gzipChunkedGoogleResponse.txt differ diff --git a/Bench4Q-Master/RecordScriptTestCase/gzipChunkedGoogleResponseBody.txt b/Bench4Q-Master/RecordScriptTestCase/gzipChunkedGoogleResponseBody.txt new file mode 100644 index 00000000..e66ba9ff Binary files /dev/null and b/Bench4Q-Master/RecordScriptTestCase/gzipChunkedGoogleResponseBody.txt differ diff --git a/Bench4Q-Master/RecordScriptTestCase/responsBodyAfterDeal.txt b/Bench4Q-Master/RecordScriptTestCase/responsBodyAfterDeal.txt new file mode 100644 index 00000000..e69de29b diff --git a/Bench4Q-Master/RecordScriptTestCase/scriptBriefResultModel.xml b/Bench4Q-Master/RecordScriptTestCase/scriptBriefResultModel.xml new file mode 100644 index 00000000..b0a4679a --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/scriptBriefResultModel.xml @@ -0,0 +1,16 @@ + + + 0 + 0 + 0 + 1203 + 0 + 28205 + 1774 + 559 + 3172 + 22154 + 5245392 + + 40 + \ No newline at end of file diff --git a/Bench4Q-Master/RecordScriptTestCase/simpleResponse.txt b/Bench4Q-Master/RecordScriptTestCase/simpleResponse.txt new file mode 100644 index 00000000..67501f04 --- /dev/null +++ b/Bench4Q-Master/RecordScriptTestCase/simpleResponse.txt @@ -0,0 +1,26 @@ +HTTP/1.1 200 OK +Server: Apache-Coyote/1.1 +Accept-Ranges: bytes +ETag: W/"532-1386125334307" +Last-Modified: Wed, 04 Dec 2013 02:48:54 GMT +Content-Type: text/html +Content-Length: 532 +Date: Mon, 09 Dec 2013 07:03:15 GMT + + + + Bench4Q Test Case + + + + + + No this one + No this one + No this one + + + + + + diff --git a/Bench4Q-Master/ScriptParameterization/79/param1.txt b/Bench4Q-Master/ScriptParameterization/79/param1.txt new file mode 100644 index 00000000..7eb8d5f4 --- /dev/null +++ b/Bench4Q-Master/ScriptParameterization/79/param1.txt @@ -0,0 +1 @@ +key=set;value=nv \ No newline at end of file diff --git a/Bench4Q-Master/ScriptParameterization/79/param2.txt b/Bench4Q-Master/ScriptParameterization/79/param2.txt new file mode 100644 index 00000000..aa40ea43 --- /dev/null +++ b/Bench4Q-Master/ScriptParameterization/79/param2.txt @@ -0,0 +1 @@ +everyThing ok = ok \ No newline at end of file diff --git a/Bench4Q-Master/descriptor.xml b/Bench4Q-Master/descriptor.xml new file mode 100644 index 00000000..4454ef3a --- /dev/null +++ b/Bench4Q-Master/descriptor.xml @@ -0,0 +1,25 @@ + + + publish + + tar.gz + + false + + + lib + false + false + runtime + + + + + target/bench4q-master.jar + / + + + \ No newline at end of file diff --git a/Bench4Q-Master/pom.xml b/Bench4Q-Master/pom.xml new file mode 100644 index 00000000..042d212d --- /dev/null +++ b/Bench4Q-Master/pom.xml @@ -0,0 +1,167 @@ + + 4.0.0 + org.bench4q + bench4q-master + jar + 0.0.1-SNAPSHOT + Bench4Q Master + Bench4Q Master + + TCSE, ISCAS + + + + junit + junit + 4.11 + test + + + org.springframework + spring-webmvc + 3.2.5.RELEASE + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.12 + + + org.hibernate + hibernate-core + 4.3.0.Beta3 + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + 1.0.0.Draft-16 + + + mysql + mysql-connector-java + 5.1.25 + + + log4j + log4j + 1.2.17 + + + commons-httpclient + commons-httpclient + 3.1 + + + org.python + jython + 2.7-b1 + + + org.springframework + spring-test + 3.2.5.RELEASE + + + org.quartz-scheduler + quartz + 1.8.5 + + + org.springframework + spring-core + 3.2.5.RELEASE + + + org.slf4j + slf4j-simple + 1.7.5 + + + + jfree + jfreechart + 1.0.13 + + + + org.eclipse.birt.runtime.3_7_1 + com.lowagie.text + 2.1.7 + + + org.apache.portals.jetspeed-2 + jetspeed-fileutils-maven-plugin + 2.2.2 + maven-plugin + + + org.bench4q + bench4q-share + 0.0.1-SNAPSHOT + + + org.eclipse.jetty + jetty-servlet + 9.1.0.RC2 + + + org.eclipse.jetty + jetty-server + 9.1.0.RC2 + + + + org.jsoup + jsoup + 1.7.3 + + + + org.apache.httpcomponents + httpcore-nio + 4.3 + + + + + + maven-jar-plugin + + + + org.bench4q.master.Main + true + lib/ + + + + + + maven-assembly-plugin + + + make-zip + package + + single + + + + descriptor.xml + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + bench4q-master + + \ No newline at end of file diff --git a/Bench4Q-Master/relative Docs/bench4q year final.pptx b/Bench4Q-Master/relative Docs/bench4q year final.pptx new file mode 100644 index 00000000..a6974b02 Binary files /dev/null and b/Bench4Q-Master/relative Docs/bench4q year final.pptx differ diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/Main.java b/Bench4Q-Master/src/main/java/org/bench4q/master/Main.java new file mode 100644 index 00000000..7e22673a --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/Main.java @@ -0,0 +1,57 @@ +package org.bench4q.master; + +import java.io.InputStream; +import java.util.Properties; +import org.apache.log4j.Logger; + +/** + * + * @author coderfengyun + * + */ +public class Main { + private static Logger logger = Logger.getLogger(Main.class); + public static int Min_Sample_Cycle_InSecond = 10; + public static int MAX_FAIL_TIMES = 10; + public static int MIN_EXECUTE_INTERVAL_IN_SECONDS = 600; + public static int PICK_CYCLE_IN_SECONDS = 60; + + public static void main(String[] args) { + try { + MasterServer masterServer = new MasterServer(getPortToServe()); + masterServer.start(); + } catch (Exception e) { + e.printStackTrace(); + return; + } + } + + public static int getPortToServe() { + int portToUse = 0; + Properties prop = new Properties(); + String configFile = ""; + try { + InputStream inputStream = Main.class.getClassLoader() + .getResourceAsStream( + "org/bench4q/master/config/ServerPort.properties"); + prop.load(inputStream); + portToUse = Integer.parseInt(prop.getProperty("portToServe")); + MAX_FAIL_TIMES = Integer.parseInt(prop.getProperty("maxFailTime")); + MIN_EXECUTE_INTERVAL_IN_SECONDS = Integer.parseInt(prop + .getProperty("minExcuteIntervalInSeconds")); + PICK_CYCLE_IN_SECONDS = Integer.parseInt(prop + .getProperty("pickTestPlanCycleInSeconds")); + Min_Sample_Cycle_InSecond = Integer.parseInt(prop + .getProperty("minSampleCycleInSeconds")); + } catch (Exception e) { + portToUse = 8080; + MAX_FAIL_TIMES = 10; + MIN_EXECUTE_INTERVAL_IN_SECONDS = 600; + PICK_CYCLE_IN_SECONDS = 60; + Min_Sample_Cycle_InSecond = 10; + logger.error("There is no config file for port to serve! where path is " + + configFile); + } + return portToUse; + } +} diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/MasterServer.java b/Bench4Q-Master/src/main/java/org/bench4q/master/MasterServer.java new file mode 100644 index 00000000..cd054cb0 --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/MasterServer.java @@ -0,0 +1,75 @@ +package org.bench4q.master; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.springframework.web.servlet.DispatcherServlet; + +/** + * + * @author coderfengyun + * + */ +public class MasterServer { + private Server server; + private int port; + + private Server getServer() { + return server; + } + + private void setServer(Server server) { + this.server = server; + } + + private int getPort() { + return port; + } + + private void setPort(int port) { + this.port = port; + } + + public MasterServer(int port) { + this.setPort(port); + } + + public boolean start() { + try { + this.setServer(new Server(this.getPort())); + ServletContextHandler servletContextHandler = new ServletContextHandler(); + ServletHolder servletHolder = servletContextHandler.addServlet( + DispatcherServlet.class, "/"); + servletHolder + .setInitParameter("contextConfigLocation", + "classpath*:/org/bench4q/master/config/application-context.xml"); + servletHolder.setInitOrder(1); + this.getServer().setHandler(servletContextHandler); + this.getServer().start(); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean stop() { + try { + if (this.getServer() != null) { + for (Connector connector : this.getServer().getConnectors()) { + if (connector != null) { + connector.shutdown(); + } + } + this.getServer().stop(); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } finally { + this.setServer(null); + } + } +} diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/TestPlunginHelper.java b/Bench4Q-Master/src/main/java/org/bench4q/master/TestPlunginHelper.java new file mode 100644 index 00000000..cbd75b48 --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/TestPlunginHelper.java @@ -0,0 +1,62 @@ +package org.bench4q.master; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import org.bench4q.share.models.master.plugin.MethodModel; +import org.bench4q.share.models.master.plugin.MethodParamModel; +import org.bench4q.share.models.master.plugin.ParamTypeEnum; +import org.bench4q.share.models.master.plugin.PluginModel; +import org.bench4q.share.models.master.plugin.MethodParamPropertyModel; + +; + +public class TestPlunginHelper { + + public static PluginModel createOnePlugin() { + PluginModel plugin = new PluginModel(); + MethodModel method = new MethodModel(); + MethodParamModel methodParamModelUrl = new MethodParamModel(); + methodParamModelUrl.setLable("input url"); + methodParamModelUrl.setName("url"); + methodParamModelUrl.setMethodParamProperties(generatePropertyForField()); + methodParamModelUrl.setParamType(ParamTypeEnum.Field); + + MethodParamModel methodParamsParamModel = new MethodParamModel(); + methodParamsParamModel.setName("queryparams"); + methodParamsParamModel.setLable("key=value"); + methodParamsParamModel.setMethodParamProperties(generatePropertyForMulti()); + methodParamsParamModel.setParamType(ParamTypeEnum.MultiField); + Set methodParams = new HashSet(); + methodParams.add(methodParamModelUrl); + methodParams.add(methodParamsParamModel); + method.setName("get"); + method.setMethodParams(methodParams); + + Set methods = new HashSet(); + methods.add(method); + plugin.setMethods(methods); + plugin.setName("http" + UUID.randomUUID()); + return plugin; + + } + private static Set generatePropertyForField() { + Set metList = new HashSet(); + MethodParamPropertyModel methodParamPropertyModel = new MethodParamPropertyModel(); + methodParamPropertyModel.setKey("size"); + methodParamPropertyModel.setValue("20"); + metList.add(methodParamPropertyModel); + return metList; + + } + private static Set generatePropertyForMulti() { + Set metList = new HashSet(); + MethodParamPropertyModel methodParamPropertyModel = new MethodParamPropertyModel(); + methodParamPropertyModel.setKey("size"); + methodParamPropertyModel.setValue("20"); + metList.add(methodParamPropertyModel); + return metList; + + } +} diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/api/AgentController.java b/Bench4Q-Master/src/main/java/org/bench4q/master/api/AgentController.java new file mode 100644 index 00000000..097a4210 --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/api/AgentController.java @@ -0,0 +1,95 @@ +package org.bench4q.master.api; + +import java.util.ArrayList; +import java.util.List; + +import org.bench4q.master.domain.entity.Agent; +import org.bench4q.master.domain.factory.BusinessModelMapFactory; +import org.bench4q.master.domain.service.AgentService; +import org.bench4q.master.domain.service.UserService; +import org.bench4q.share.models.master.AgentModel; +import org.bench4q.share.models.master.AgentResponseModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Component +@RequestMapping("/agentManage") +public class AgentController extends BaseController { + private AgentService agentPoolService; + + public AgentService getAgentService() { + return agentPoolService; + } + + @Autowired + private void setAgentPoolService(AgentService agentPoolService) { + this.agentPoolService = agentPoolService; + } + + @RequestMapping(value = "/addAgentToPool", method = RequestMethod.POST) + @ResponseBody + public AgentResponseModel addAgentToPool(@RequestBody AgentModel agent) { + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + return setAgentResponseModel(false, + "you don't have the power to add agent to pool!", + new ArrayList()); + } + synchronized (this.getAgentService().getAgentLock()) { + if (!this.getAgentService().addAgentToPool( + BusinessModelMapFactory.toBusiness(agent))) { + return setAgentResponseModel(false, + "add agent to DB fails in addAgentToPool", + new ArrayList()); + } + this.getAgentService().getAgentLock().notifyAll(); + return setAgentResponseModel(true, "", new ArrayList()); + } + } + + @RequestMapping(value = "/removeAgentFromPool", method = RequestMethod.GET) + @ResponseBody + public AgentResponseModel removeAgentFromPool(@RequestParam int agentId, + @RequestParam String hostName) { + + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + return setAgentResponseModel(false, + "you don't have the power to remove agent from pool!", + new ArrayList()); + } + synchronized (this.getAgentService().getAgentLock()) { + if (!this.getAgentService().removeAgentFromPool(agentId)) { + return setAgentResponseModel(false, + "remove agent from DB fails in removeAgentFromPool", + new ArrayList()); + } + return this.setAgentResponseModel(true, "", + new ArrayList()); + } + } + + @RequestMapping(value = "/queryAgentList", method = { RequestMethod.POST, + RequestMethod.GET }) + @ResponseBody + public AgentResponseModel queryAgentList() { + List list = this.getAgentService().loadAgentPoolFromDB(); + List modelList = new ArrayList(); + for (Agent agent : list) { + modelList.add(BusinessModelMapFactory.toModel(agent)); + } + return setAgentResponseModel(true, "", modelList); + } + + private AgentResponseModel setAgentResponseModel(boolean isSuccess, + String failCauseString, List agents) { + AgentResponseModel agentResponseModel = new AgentResponseModel(); + agentResponseModel.setSuccess(isSuccess); + agentResponseModel.setFailCauseString(failCauseString); + agentResponseModel.setAgents(agents); + return agentResponseModel; + } +} \ No newline at end of file diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/api/BaseController.java b/Bench4Q-Master/src/main/java/org/bench4q/master/api/BaseController.java new file mode 100644 index 00000000..5232b5f5 --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/api/BaseController.java @@ -0,0 +1,71 @@ +package org.bench4q.master.api; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; +import org.bench4q.master.domain.entity.User; +import org.bench4q.master.domain.service.auth.AuthenticationManager; +import org.bench4q.master.exception.Bench4QException; +import org.bench4q.master.exception.ExceptionLog; +import org.bench4q.share.models.ErrorResponseModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +public abstract class BaseController { + private HttpServletRequest request; + private AuthenticationManager authenticationManager; + protected static final String HAVE_NO_POWER = "Have no power"; + protected static final String EXCEPTION_HAPPEND = "Exception happened"; + private Logger logger = Logger.getLogger(BaseController.class); + + protected HttpServletRequest getRequest() { + return request; + } + + @Autowired + protected void setRequest(HttpServletRequest request) { + this.request = request; + } + + protected AuthenticationManager getAuthenticationManager() { + return authenticationManager; + } + + @Autowired + protected void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + @ExceptionHandler(Bench4QException.class) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ResponseBody + public ErrorResponseModel handleException(Bench4QException e) { + logger.error(ExceptionLog.getStackTrace(e)); + return ErrorResponseModel.buildErrorResponse(e.getCode(), + e.getMessage(), e.getResource()); + } + + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ResponseBody + public ErrorResponseModel handleException(RuntimeException e) { + logger.info(ExceptionLog.getStackTrace(e)); + logger.info(e.getCause()); + return ErrorResponseModel.buildErrorResponse("RUNTIME_EXCEPTION", + e.getMessage(), ""); + } + + protected User getPrincipal() { + return this.getAuthenticationManager().getPrincipal(this.getRequest()); + } + + protected boolean checkScope(byte scope) { + return this.getAuthenticationManager().checkScope(this.getRequest(), + scope); + } + +} diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/api/HomeController.java b/Bench4Q-Master/src/main/java/org/bench4q/master/api/HomeController.java new file mode 100644 index 00000000..bff6b321 --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/api/HomeController.java @@ -0,0 +1,24 @@ +package org.bench4q.master.api; + +import org.bench4q.master.domain.entity.User; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/") +public class HomeController extends BaseController { + @RequestMapping(value = { "/" }, method = RequestMethod.GET) + @ResponseBody + public String index() { + User principal = this.getPrincipal(); + String userName; + if (principal == null) { + userName = "Anonymous User"; + } else { + userName = principal.getUserName(); + } + return "Hello [" + userName + "]"; + } +} \ No newline at end of file diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/api/MonitorController.java b/Bench4Q-Master/src/main/java/org/bench4q/master/api/MonitorController.java new file mode 100644 index 00000000..49e9c9bc --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/api/MonitorController.java @@ -0,0 +1,98 @@ +package org.bench4q.master.api; + +import java.util.UUID; + +import org.bench4q.master.domain.service.MonitorResultService; +import org.bench4q.master.domain.service.UserService; +import org.bench4q.master.exception.Bench4QException; +import org.bench4q.share.models.master.MonitorPhysicalDiskResponseModel; +import org.bench4q.share.models.master.MonitorMemoryResponseModel; +import org.bench4q.share.models.master.MonitorNetworkReponseModel; +import org.bench4q.share.models.master.MonitorProcessorResponseModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping(value = "/monitorController") +public class MonitorController extends BaseController { + private MonitorResultService monitorResultService; + + private MonitorResultService getMonitorResultService() { + return monitorResultService; + } + + @Autowired + private void setMonitorResultService( + MonitorResultService monitorResultService) { + this.monitorResultService = monitorResultService; + } + + @RequestMapping(value = "/logicDiskMonitorSUTInfo/{testPlanRunId}/{hostName}/{port}/{duationBegin}", method = RequestMethod.GET) + @ResponseBody + public MonitorPhysicalDiskResponseModel logicDiskMonitorSUTInfo( + @PathVariable UUID testPlanRunId, @PathVariable String hostName, + @PathVariable int port, @PathVariable long duationBegin) + throws Bench4QException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "/{testPlanRunId}/script/{scriptId}/{fieldName}"); + } + MonitorPhysicalDiskResponseModel ret = this.getMonitorResultService() + .physicalDiskDiskResults(testPlanRunId, hostName, port, + duationBegin); + return ret == null ? new MonitorPhysicalDiskResponseModel() : ret; + } + + @RequestMapping(value = "/memorySUTInfo", method = { RequestMethod.GET, + RequestMethod.POST }) + @ResponseBody + public MonitorMemoryResponseModel memorySUTInfo( + @RequestParam UUID testPlanRunId, @RequestParam String hostName, + @RequestParam int port, @RequestParam long duationBegin) + throws Bench4QException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "/memorySUTInfo"); + } + MonitorMemoryResponseModel ret = this.getMonitorResultService() + .loadMemoryModels(testPlanRunId, hostName, port, duationBegin); + return ret == null ? new MonitorMemoryResponseModel() : ret; + } + + @RequestMapping(value = "/processorSUTInfo", method = { RequestMethod.GET }) + @ResponseBody + public MonitorProcessorResponseModel processorSUTInfo( + @RequestParam UUID testPlanRunId, @RequestParam String hostName, + @RequestParam int port, @RequestParam long duationBegin) + throws Bench4QException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "/processorSUTInfo"); + } + MonitorProcessorResponseModel ret = this.getMonitorResultService() + .loadProcessorModels(testPlanRunId, hostName, port, + duationBegin); + return ret == null ? new MonitorProcessorResponseModel() : ret; + } + + @RequestMapping(value = "/networkInfo", method = { RequestMethod.GET }) + @ResponseBody + public MonitorNetworkReponseModel networkInfo( + @RequestParam UUID testPlanRunId, @RequestParam String hostName, + @RequestParam int port, @RequestParam long duationBegin) + throws Bench4QException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "/networkInfo"); + } + MonitorNetworkReponseModel ret = this.getMonitorResultService() + .loadNetworkInterfaceModels(testPlanRunId, hostName, port, + duationBegin); + return ret == null ? new MonitorNetworkReponseModel() : ret; + } +} diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/api/PluginController.java b/Bench4Q-Master/src/main/java/org/bench4q/master/api/PluginController.java new file mode 100644 index 00000000..dbfe0df9 --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/api/PluginController.java @@ -0,0 +1,128 @@ +package org.bench4q.master.api; + +import org.apache.log4j.Logger; +import org.bench4q.master.TestPlunginHelper; +import org.bench4q.master.domain.service.PluginService; +import org.bench4q.master.domain.service.UserService; +import org.bench4q.master.exception.Bench4QException; +import org.bench4q.master.exception.ExceptionLog; +import org.bench4q.share.models.master.plugin.PluginGUI; +import org.bench4q.share.models.master.plugin.PluginModel; +import org.bench4q.share.models.master.plugin.PluginResponseModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/plugin") +public class PluginController extends BaseController { + private Logger logger = Logger.getLogger(PluginController.class); + private PluginService pluginService; + + public PluginService getPluginService() { + return pluginService; + } + + @Autowired + public void setPluginService(PluginService pluginService) { + this.pluginService = pluginService; + } + + @RequestMapping("/add") + @ResponseBody + public void addPluginToDataBase() throws Bench4QException{ + PluginModel pluginModel=TestPlunginHelper.createOnePlugin(); + this.getPluginService().addPlugin(pluginModel); + } + @RequestMapping("/loadPluginList") + @ResponseBody + public PluginResponseModel loadPluginList() throws Bench4QException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "/loadPluginList"); + } + PluginResponseModel pluginResponseModel = new PluginResponseModel(); + pluginResponseModel.setPluginList(this.getPluginService() + .getPluginNameList()); + + pluginResponseModel.setSuccess(true); + return pluginResponseModel; + } + + @RequestMapping(value = "loadMethodList/{pluginName}", method = { + RequestMethod.GET, RequestMethod.POST }) + @ResponseBody + public PluginResponseModel getMethodList( + @PathVariable("pluginName") String pluginName) + throws Bench4QException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "/loadMethodList/{pluginName}"); + } + try { + PluginResponseModel pluginResponseModel = new PluginResponseModel(); + pluginResponseModel.setMethodList(this.getPluginService() + .getMethodNameInPlugin(pluginName)); + pluginResponseModel.setSuccess(true); + return pluginResponseModel; + } catch (Exception e) { + logger.error(ExceptionLog.getStackTrace(e)); + return null; + } + } + + @RequestMapping(value = "loadMethodParams/{pluginName}/{methodName}", method = { + RequestMethod.GET, RequestMethod.POST }) + @ResponseBody + public PluginResponseModel getMethodParams( + @PathVariable("pluginName") String pluginName, + @PathVariable("methodName") String methodName) + throws Bench4QException { + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "loadMethodParams/{pluginName}/{methodName}"); + } + PluginResponseModel pluginResponseModel = new PluginResponseModel(); + pluginResponseModel.setMethosMethodParamModels(this.getPluginService() + .getMethodParamModelsInPlugin(pluginName, methodName)); + pluginResponseModel.setSuccess(true); + return pluginResponseModel; + } + + @RequestMapping(value = "/addPlugin", method = { RequestMethod.PUT }) + @ResponseBody + public PluginResponseModel addPlugin(@RequestBody PluginGUI pluginGUI) + throws Bench4QException { + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "loadMethodParams/{pluginName}/{methodName}"); + } + PluginResponseModel pluginResponseModel = new PluginResponseModel(); + pluginResponseModel.setSuccess(this.getPluginService().addPlugin( + pluginGUI.getPlugin())); + return pluginResponseModel; + + } + + @RequestMapping(value = "/deletePlugin/{pluginName}", method = { + RequestMethod.GET, RequestMethod.POST }) + @ResponseBody + public PluginResponseModel deletePlugin( + @PathVariable("pluginName") String pluginName) + throws Bench4QException { + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + throw new Bench4QException(400 + "", "not permitted", + "loadMethodParams/{pluginName}/{methodName}"); + } + PluginResponseModel pluginResponseModel = new PluginResponseModel(); + pluginResponseModel.setSuccess(this.getPluginService().deletePlugin( + pluginName)); + return pluginResponseModel; + + } + +} diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/api/RecordPortController.java b/Bench4Q-Master/src/main/java/org/bench4q/master/api/RecordPortController.java new file mode 100644 index 00000000..4058d116 --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/api/RecordPortController.java @@ -0,0 +1,116 @@ +package org.bench4q.master.api; + +import java.util.ArrayList; +import java.util.List; + +import org.bench4q.master.domain.entity.Port; +import org.bench4q.master.domain.factory.BusinessModelMapFactory; +import org.bench4q.master.domain.service.PortPoolService; +import org.bench4q.master.domain.service.UserService; +import org.bench4q.share.models.master.OrganizeRecordPortResponseModel; +import org.bench4q.share.models.master.PortModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/RecordPort") +public class RecordPortController extends BaseController { + + private PortPoolService portPoolService = new PortPoolService(); + private static Object syncObject = new Object(); + + public PortPoolService getPortPoolService() { + return portPoolService; + } + + @Autowired + private void setPortPoolService(PortPoolService portPoolService) { + this.portPoolService = portPoolService; + } + + public static Object getSyncObject() { + return syncObject; + } + + public static void setSyncObject(Object syncObject) { + RecordPortController.syncObject = syncObject; + } + + @RequestMapping(value = "/addPortToPortPool", method = { + RequestMethod.POST, RequestMethod.GET }) + @ResponseBody + public OrganizeRecordPortResponseModel addPortToPortPool( + @RequestParam int port) { + + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + return _buildResponseModel(false, + "you don't hava the power to add port to pool!", + new ArrayList()); + } + + if (!this.getPortPoolService().addPortToDBPool(port)) { + return _buildResponseModel(false, "add to DB pool fails", + new ArrayList()); + } + return _buildResponseModel(true, "", new ArrayList()); + } + + @RequestMapping(value = "/removePortFromPool", method = RequestMethod.POST) + @ResponseBody + public OrganizeRecordPortResponseModel removePortFromPool( + @RequestParam int portId) { + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + return _buildResponseModel(false, + "you don't hava the power to remove port from pool!", + new ArrayList()); + } + if (!this.getPortPoolService().removePortFromDBPool(portId)) { + return _buildResponseModel(false, "remove from local fails", + new ArrayList()); + } + return _buildResponseModel(true, "", new ArrayList()); + } + + @RequestMapping(value = "/loadPortList", method = RequestMethod.POST) + @ResponseBody + public OrganizeRecordPortResponseModel loadPortList() { + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + return _buildResponseModel(false, + "you don't hava the power to load!", + new ArrayList()); + } + List portModels = new ArrayList(); + for (Port port : this.portPoolService.loadPortList()) { + portModels.add(BusinessModelMapFactory.toModel(port)); + } + return this._buildResponseModel(true, "", portModels); + } + + @RequestMapping(value = "/editPort", method = { RequestMethod.GET, + RequestMethod.POST }) + @ResponseBody + public OrganizeRecordPortResponseModel editPort(@RequestParam PortModel port) { + if (!this.checkScope(UserService.SUPER_AUTHENTICATION)) { + return _buildResponseModel(false, "you don't have power to edit", + new ArrayList()); + } + + return this._buildResponseModel( + this.getPortPoolService().editPort( + BusinessModelMapFactory.toBusiness(port)), "", + new ArrayList()); + } + + private OrganizeRecordPortResponseModel _buildResponseModel( + boolean success, String failString, List ports) { + OrganizeRecordPortResponseModel result = new OrganizeRecordPortResponseModel(); + result.setSuccess(success); + result.setFailCauseString(failString); + result.setPortModels(ports); + return result; + } +} diff --git a/Bench4Q-Master/src/main/java/org/bench4q/master/api/ScriptController.java b/Bench4Q-Master/src/main/java/org/bench4q/master/api/ScriptController.java new file mode 100644 index 00000000..dcc17a0b --- /dev/null +++ b/Bench4Q-Master/src/main/java/org/bench4q/master/api/ScriptController.java @@ -0,0 +1,308 @@ +package org.bench4q.master.api; + +import java.io.File; +import java.net.UnknownHostException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import javax.xml.bind.JAXBException; + +import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; +import org.bench4q.master.domain.entity.Port; +import org.bench4q.master.domain.entity.Script; +import org.bench4q.master.domain.factory.BusinessModelMapFactory; +import org.bench4q.master.domain.service.PortPoolService; +import org.bench4q.master.domain.service.ScriptService; +import org.bench4q.master.domain.service.UserService; +import org.bench4q.master.exception.Bench4QException; +import org.bench4q.master.exception.ExceptionLog; +import org.bench4q.master.scriptrecord.ScriptCapturer; +import org.bench4q.share.helper.MarshalHelper; +import org.bench4q.share.models.agent.RunScenarioModel; +import org.bench4q.share.models.master.OperateScriptServerResponseModel; +import org.bench4q.share.models.master.ScriptModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/RecordScript") +public class ScriptController extends BaseController { + private ScriptCapturer scriptCapturer; + private ScriptService scriptService; + private PortPoolService portPoolService = new PortPoolService(); + private static final Object PORT_LOCK = new Object(); + private Logger logger = Logger.getLogger(ScriptController.class); + + private ScriptCapturer getScriptCapturer() { + return scriptCapturer; + } + + @Autowired + private void setScriptCapturer(ScriptCapturer scriptCapturer) { + this.scriptCapturer = scriptCapturer; + } + + private ScriptService getScriptService() { + return scriptService; + } + + @Autowired + private void setScriptService(ScriptService scriptService) { + this.scriptService = scriptService; + } + + private PortPoolService getPortPoolService() { + return portPoolService; + } + + @Autowired + private void setPortPoolService(PortPoolService portPoolService) { + this.portPoolService = portPoolService; + } + + @RequestMapping(value = "/test/{port}", method = RequestMethod.GET) + @ResponseBody + public OperateScriptServerResponseModel testProxyConnection(int port) { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + return buildReponseModel(false, + "has no power for recording script!!!", "", -1, null, null, + null); + } + // TODO: + return null; + } + + @RequestMapping(value = "/startScriptRecordServer", method = { + RequestMethod.GET, RequestMethod.POST }) + @ResponseBody + public OperateScriptServerResponseModel startScriptRecordServer() + throws UnknownHostException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + return buildReponseModel(false, + "has no power for recording script!!!", "", -1, null, null, + null); + } + Port port = new Port(); + synchronized (PORT_LOCK) { + port = this.getPortPoolService().getAPortNotInUse(); + if (port == null) { + return buildReponseModel(false, "port is in use!", "", -1, + null, null, null); + } + } + UUID uuid = UUID.randomUUID(); + this.getScriptCapturer().startRecord(port.getPort(), + buildScriptSavePath(), uuid.toString()); + + return buildReponseModel(true, "", this.getScriptCapturer() + .getIpHttpCaptureServerAdress(), port.getPort(), null, null, + uuid.toString()); + } + + private String buildScriptSavePath() { + String dirString = "Scripts" + System.getProperty("file.separator") + + this.getPrincipal().getUserName() + + System.getProperty("file.separator") + + new SimpleDateFormat("yyyyMMdd").format(new Date()); + File dirFile = new File(dirString); + if (!dirFile.exists()) { + dirFile.mkdirs(); + } + return dirString; + } + + @RequestMapping(value = "/stopScriptRecordServer", method = { + RequestMethod.POST, RequestMethod.GET }) + @ResponseBody + public OperateScriptServerResponseModel stopScriptRecordServer( + @RequestParam int port, @RequestParam String fileNameUUID) { + if (!checkScope(UserService.NORAML_AUTHENTICATION)) { + return buildReponseModel(false, + "has no power for stopScriptCapture!!!", "", -1, null, + null, null); + } + + this.getScriptCapturer().stopCurrentRecord(port); + synchronized (PORT_LOCK) { + this.getPortPoolService().backPort(port); + } + + return buildReponseModel(true, "RecordServer stop", "", port, null, + null, fileNameUUID); + } + + @RequestMapping(value = "/saveScriptToDB", method = { RequestMethod.GET, + RequestMethod.POST }) + @ResponseBody + public OperateScriptServerResponseModel saveScriptToDB( + @RequestParam String scriptName, @RequestParam int port, + @RequestParam String fileNameUUID) { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + return buildReponseModel(false, + "saveScriptToDB check your scope fail!", "", -1, null, + null, null); + } + + File file = new File(buildScriptSavePath() + + System.getProperty("file.separator") + fileNameUUID + ".xml"); + if (!file.exists()) { + return buildReponseModel(false, "no that script", null, -1, null, + null, fileNameUUID); + } + try { + String content = FileUtils.readFileToString(file); + logger.info("when saveToDB, scriptContent is " + content); + boolean success = this.getScriptService().saveScript(scriptName, + this.getPrincipal().getId(), content); + // this.getUserService().add + return buildReponseModel(success, "Save to DataBase!!", "", port, + null, null, null); + } catch (Exception e) { + return buildReponseModel(false, "exception when read from file", + null, -1, null, null, fileNameUUID); + } + } + + @RequestMapping(value = "/uploadScript/{scriptName}", method = RequestMethod.PUT) + @ResponseBody + public OperateScriptServerResponseModel uploadScriptToDB( + @PathVariable String scriptName, + @RequestBody RunScenarioModel scenarioModel) + throws Bench4QException { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + throw new Bench4QException(HAVE_NO_POWER, HAVE_NO_POWER + + "for upload a script", "/uploadScript"); + } + try { + boolean success = this.getScriptService().saveScript( + scriptName, + this.getPrincipal().getId(), + MarshalHelper + .marshal(RunScenarioModel.class, scenarioModel)); + return buildReponseModel(success, null, null, -1, null, null, null); + } catch (JAXBException e) { + this.logger.error(ExceptionLog.getStackTrace(e)); + return buildReponseModel(false, + "The script is not in the right format", null, -1, null, + null, null); + } + } + + @RequestMapping(value = "/loadScriptList", method = { RequestMethod.POST, + RequestMethod.GET }) + @ResponseBody + public OperateScriptServerResponseModel loadScriptList() { + if (!this.checkScope(UserService.NORAML_AUTHENTICATION)) { + return null; + } + List + + + + diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_AgentRepository.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_AgentRepository.java new file mode 100644 index 00000000..c34360dc --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_AgentRepository.java @@ -0,0 +1,42 @@ +package org.bench4q.master.test.repository; + +import static org.junit.Assert.*; + +import org.bench4q.master.domain.entity.Agent; +import org.bench4q.master.domain.repository.AgentRepository; +import org.bench4q.master.domain.service.AgentService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_AgentRepository { + private AgentRepository agentRepoitory; + + private AgentRepository getAgentRepoitory() { + return agentRepoitory; + } + + @Autowired + private void setAgentRepoitory(AgentRepository agentRepoitory) { + this.agentRepoitory = agentRepoitory; + } + + @Test + public void testAddAgent() { + String hostNameForTest = "133.133.12.95"; + int portForTest = 6565; + assertTrue(this.getAgentRepoitory().attach( + Agent.createAgentWithoutId(hostNameForTest, portForTest))); + Agent agent = this.getAgentRepoitory().getAgentBy(hostNameForTest); + assertNotNull(agent); + assertEquals(hostNameForTest, agent.getHostName()); + assertEquals(portForTest, agent.getPort()); + assertEquals(500, agent.getMaxLoad()); + assertEquals(AgentService.AGENT_STATUS_Idel, agent.getCurrentStatus()); + assertTrue(this.getAgentRepoitory().detach(agent.getId())); + } +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_PluginRepository.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_PluginRepository.java new file mode 100644 index 00000000..9d2dddc2 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_PluginRepository.java @@ -0,0 +1,94 @@ +package org.bench4q.master.test.repository; + +import static org.junit.Assert.*; + +import org.bench4q.master.TestPlunginHelper; +import org.bench4q.master.domain.entity.plugin.MethodParam; +import org.bench4q.master.domain.entity.plugin.Plugin; +import org.bench4q.master.domain.factory.PluginFactory; +import org.bench4q.master.domain.repository.PluginRepository; +import org.bench4q.master.exception.Bench4QException; +import org.bench4q.share.models.master.plugin.PluginModel; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_PluginRepository { + private PluginRepository pluginRepository; + private String pluginName; + private PluginFactory pluginFactory; + + public PluginRepository getPluginRepository() { + return pluginRepository; + } + + @Autowired + public void setPluginRepository(PluginRepository pluginRepository) { + this.pluginRepository = pluginRepository; + } + + public PluginFactory getPluginFactory() { + return pluginFactory; + } + + @Autowired + public void setPluginFactory(PluginFactory pluginFactory) { + this.pluginFactory = pluginFactory; + } + + @Before + public void setUp() throws Bench4QException { + pluginName = addPlugin(); + } + + @Test + public void testGetPlugin() { + assertNotNull(this.getPluginRepository().getPlugin(pluginName)); + } + + @Test + public void TestLoadMethodParam() { + Plugin plugin = this.getPluginRepository().getPlugin(pluginName); + MethodParam methodParam = plugin.getPluginMethods().iterator().next() + .getMethodParams().iterator().next(); + + System.out.println(methodParam.getParamType().getClass()); + } + + @Test + public void testGetMethodList() throws Bench4QException { + Plugin plugin = this.getPluginRepository().getPlugin(pluginName); + assertNotNull(plugin); + assertEquals(1, plugin.getPluginMethods().size()); + } + + @Test + public void testLoadPlugin() throws Bench4QException { + + int countBeforeInsert = this.getPluginRepository().loadPlugins().size(); + String insertPlugin = addPlugin(); + assertEquals(countBeforeInsert + 1, this.getPluginRepository() + .loadPlugins().size()); + this.getPluginRepository().detach(insertPlugin); + + } + + @After + public void clear() throws Bench4QException { + /* this.getPluginRepository().detach(pluginName); */ + } + + private String addPlugin() throws Bench4QException { + PluginModel pluginModel = TestPlunginHelper.createOnePlugin(); + this.getPluginRepository().attatch( + this.getPluginFactory().createPluginEntity(pluginModel)); + return pluginModel.getName(); + + } +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_TestPlanRepository.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_TestPlanRepository.java new file mode 100644 index 00000000..6d8c27e8 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_TestPlanRepository.java @@ -0,0 +1,67 @@ +package org.bench4q.master.test.repository; + +import static org.junit.Assert.*; + +import java.util.UUID; + +import org.bench4q.master.domain.entity.TestPlan; +import org.bench4q.master.test.TestBase_MakeUpTestPlan; +import org.bench4q.share.enums.master.TestPlanStatus; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_TestPlanRepository extends TestBase_MakeUpTestPlan { + @Test + public void testGetTestPlan() { + TestPlan testPlan = this.getTestPlanRepository().getTestPlanBy( + getTestPlanRunIdUuid()); + assertNotNull(testPlan); + assertEquals(getTestPlanRunIdUuid(), + UUID.fromString(testPlan.getTestPlanRunId())); + } + + @Test + public void testLoadEntities() { + int sizeBefore = this.getTestPlanRepository() + .loadEntities(this.getUserRepository().getUser("admin")).size(); + assertTrue(sizeBefore > 0); + System.out.println(sizeBefore); + submitATestPlanWithTwoScript(); + int sizeAfter = this.getTestPlanRepository() + .loadEntities(this.getUserRepository().getUser("admin")).size(); + assertEquals(sizeBefore + 1, sizeAfter); + } + + @Test + public void testUpdateEntity() { + TestPlan testPlanDB = this.getTestPlanRepository().getTestPlanBy( + getTestPlanRunIdUuid()); + assertNotNull(testPlanDB); + assertEquals(TestPlanStatus.NotStart.name(), + testPlanDB.getCurrentStatus()); + testPlanDB.setCurrentStatus(TestPlanStatus.Complete.name()); + this.getTestPlanRepository().updateEntity(testPlanDB); + TestPlan afterModify = this.getTestPlanRepository().getTestPlanBy( + getTestPlanRunIdUuid()); + assertEquals(TestPlanStatus.Complete.name(), + afterModify.getCurrentStatus()); + } + + @Before + public void prepare() { + this.submitATestPlanWithOneScript(); + } + + @After + public void restoreStatus() { + this.getTestPlanRepository().detach( + this.getTestPlanRepository() + .getTestPlanBy(getTestPlanRunIdUuid()).getId()); + } +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_UserRepository.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_UserRepository.java new file mode 100644 index 00000000..1b17f9e0 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/repository/Test_UserRepository.java @@ -0,0 +1,99 @@ +package org.bench4q.master.test.repository; + +import static org.junit.Assert.*; + +import org.bench4q.master.domain.entity.User; +import org.bench4q.master.domain.repository.UserRepository; +import org.bench4q.master.helper.HashHelper; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_UserRepository { + private UserRepository userRepository; + private HashHelper hashHelper; + private User userForTest; + + private UserRepository getUserRepository() { + return userRepository; + } + + @Autowired + private void setUserRepository(UserRepository userRepository) { + this.userRepository = userRepository; + } + + private HashHelper getHashHelper() { + return hashHelper; + } + + @Autowired + private void setHashHelper(HashHelper hashHelper) { + this.hashHelper = hashHelper; + init(); + } + + private User getUserForTest() { + return userForTest; + } + + private void setUserForTest(User userForTest) { + this.userForTest = userForTest; + } + + public Test_UserRepository() { + } + + @Before + public void init() { + User user = new User(); + user.setPassword(this.getHashHelper().sha1Hash("test1")); + user.setUserName("test1"); + user.setScope((byte) 0); + this.setUserForTest(user); + } + + @Test + public void initTest() { + assertNotNull(this.getUserRepository()); + } + + @Test + public void testAttach() { + assertTrue(this.getUserRepository().attatch(this.getUserForTest())); + } + + @After + public void cleanUp() { + this.getUserRepository().detach(this.getUserForTest().getUserName()); + } + + @Test + public void testIsExist() { + this.getUserRepository().attatch(this.getUserForTest()); + assertTrue(this.getUserRepository().isExist(this.getUserForTest())); + } + + @Test + public void testGetUserByName() { + this.getUserRepository().attatch(this.getUserForTest()); + assertNotNull(this.getUserRepository().getUser("test1")); + } + + @Test + public void testGetEntity() { + assertNotNull(this.getUserRepository().getEntity(5)); + } + + @Test + public void testUpdateEntity() { + // This test can reference to the test Of the + // Test_UserService.testAddScript + } +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_AgentService.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_AgentService.java new file mode 100644 index 00000000..894b9115 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_AgentService.java @@ -0,0 +1,175 @@ +package org.bench4q.master.test.service; + +import static org.junit.Assert.*; + +import org.bench4q.master.domain.entity.Agent; +import org.bench4q.master.domain.repository.AgentRepository; +import org.bench4q.master.domain.service.AgentService; +import org.bench4q.master.testplan.highavailable.HighAvailablePool; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_AgentService { + private static final String hostNameForTest = "133.133.12.5"; + private AgentService agentService; + private AgentRepository agentRepoitory; + private HighAvailablePool highAvailablePool; + + private AgentService getAgentService() { + return agentService; + } + + @Autowired + private void setAgentService(AgentService agentService) { + this.agentService = agentService; + } + + private AgentRepository getAgentRepoitory() { + return agentRepoitory; + } + + @Autowired + private void setAgentRepoitory(AgentRepository agentRepoitory) { + this.agentRepoitory = agentRepoitory; + } + + private HighAvailablePool getHighAvailablePool() { + return highAvailablePool; + } + + @Autowired + private void setHighAvailablePool(HighAvailablePool highAvailablePool) { + this.highAvailablePool = highAvailablePool; + } + + @Test + public void testAddAgentToPool() { + Agent agent = getAgentForTest(); + assertNotNull(this.getHighAvailablePool().getPool() + .get(hostNameForTest)); + assertNotNull(agent); + } + + private Agent getAgentForTest() { + return this.getAgentRepoitory().getAgentBy(hostNameForTest); + } + + private boolean doAddAgent() { + return this.getAgentService().addAgentToPool( + Agent.createAgentWithoutId(hostNameForTest, 6565)); + } + + @Before + public void prepare() { + doAddAgent(); + } + + @After + public void cleanUp() { + this.getAgentService().removeAgentFromPool(getAgentForTest().getId()); + } + + @Test + public void tsetRemoveAgentFromPool() { + Agent agent = getAgentForTest(); + assertTrue(agent != null); + assertTrue(this.getAgentService().removeAgentFromPool(agent.getId())); + assertNull(getAgentForTest()); + doAddAgent(); + } + + @Test + public void testLoadAgentPoolFromDB() { + this.getAgentService().removeAgentFromPool(getAgentForTest().getId()); + int sizeBeforeAdd = this.getAgentService().loadAgentPoolFromDB().size(); + doAddAgent(); + int sizeAfterAdd = this.getAgentService().loadAgentPoolFromDB().size(); + assertEquals(sizeBeforeAdd + 1, sizeAfterAdd); + } + + @Test + public void testGetLoadFromAgentWhereRequireLoad_LT_RemainLoad() { + doAddAgent(); + assertTrue(this.getAgentService() + .getLoadFromAgent(hostNameForTest, 100)); + assertEquals(400, getAgentForTest().getRemainLoad()); + } + + @Test + public void testGetLoadFromAgentWhereRequireLoad_GT_RemainLoad() { + int initialRemainLoad = getAgentForTest().getRemainLoad(); + assertFalse(this.getAgentService().getLoadFromAgent(hostNameForTest, + initialRemainLoad + 100)); + assertEquals(initialRemainLoad, getAgentForTest().getRemainLoad()); + } + + @Test + public void testGetLoadFromAgentWhereRequireLoad_LT_Zero() { + assertFalse(this.getAgentService().getLoadFromAgent(hostNameForTest, + -100)); + assertEquals(getAgentForTest().getMaxLoad(), getAgentForTest() + .getRemainLoad()); + } + + @Test + public void testBackLoadFromAgentWhereBackLoad_Plus_RemainLoad__LE_MaxLoad() { + Agent agent = getAgentForTest(); + int initialDifferenceBetweenMaxLoadAndRemainLoad = agent.getMaxLoad() + - agent.getRemainLoad(); + assertTrue(this.getAgentService().backLoadToAgent(hostNameForTest, + initialDifferenceBetweenMaxLoadAndRemainLoad)); + assertEquals(getAgentForTest().getMaxLoad(), getAgentForTest() + .getRemainLoad()); + } + + @Test + public void testBackLoadToAgentWhereBackLoad_Plus_RemainLoad_GE_MaxLoad() { + Agent agent = getAgentForTest(); + int initialDifferenceBetweenMaxLoadAndRemainLoad = agent.getMaxLoad() + - agent.getRemainLoad(); + assertTrue(initialDifferenceBetweenMaxLoadAndRemainLoad >= 0); + assertFalse(this.getAgentService().backLoadToAgent(hostNameForTest, + initialDifferenceBetweenMaxLoadAndRemainLoad + 100)); + assertEquals(initialDifferenceBetweenMaxLoadAndRemainLoad, + getAgentForTest().getMaxLoad() + - getAgentForTest().getRemainLoad()); + } + + @Test + public void testBackLoadToAgentWhereBackLoad_LT_Zero() { + int initialDifferenceBetweenMaxLoadAndRemainLoad = getAgentForTest() + .getMaxLoad() - getAgentForTest().getRemainLoad(); + assertFalse(this.getAgentService().backLoadToAgent(hostNameForTest, + -100)); + assertEquals(initialDifferenceBetweenMaxLoadAndRemainLoad, + getAgentForTest().getMaxLoad() + - getAgentForTest().getRemainLoad()); + } + + @Test + public void testResetAgent() { + assertTrue(this.getAgentService().getLoadFromAgent(hostNameForTest, + getAgentForTest().getRemainLoad() - 10)); + assertEquals(10, getAgentForTest().getRemainLoad()); + assertTrue(this.getAgentService().resetAgent(getAgentForTest())); + assertEquals(getAgentForTest().getMaxLoad(), getAgentForTest() + .getRemainLoad()); + } + + @Test + public void testUpdateAgentStatus() { + assertEquals(AgentService.AGENT_STATUS_Idel, getAgentForTest() + .getCurrentStatus()); + assertTrue(this.getAgentService().updateAgentStatus( + AgentService.AGENT_STATUS_BreakDown, hostNameForTest)); + assertEquals(AgentService.AGENT_STATUS_BreakDown, getAgentForTest() + .getCurrentStatus()); + } +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_MonitorMessenger.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_MonitorMessenger.java new file mode 100644 index 00000000..defedea1 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_MonitorMessenger.java @@ -0,0 +1,82 @@ +package org.bench4q.master.test.service; + +import static org.junit.Assert.*; + + +import org.bench4q.master.infrastructure.communication.MonitorMessenger; +import org.bench4q.share.models.monitor.MemoryModel; +import org.bench4q.share.models.monitor.MonitorMain; +import org.bench4q.share.models.monitor.NetworkInterfaceModel; +import org.bench4q.share.models.monitor.PhysicalDiskModel; +import org.bench4q.share.models.monitor.ProcessModel; +import org.bench4q.share.models.monitor.ProcessorModel; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_MonitorMessenger { + private static final int PORT = 5556; + private static final String SUT_HOST_NAME = "133.133.12.3"; + private MonitorMessenger monitorService; + + private MonitorMessenger getMonitorService() { + return monitorService; + } + + @Autowired + private void setMonitorService(MonitorMessenger monitorService) { + this.monitorService = monitorService; + } + + @Test + public void test() { + assertNotNull(this.getMonitorService()); + } + + @Test + public void testphysicalDisk() { + PhysicalDiskModel logicalDiskModel = this.getMonitorService() + .physicalDisk(SUT_HOST_NAME, 5556); + assertNotNull(logicalDiskModel); + assertNotNull(logicalDiskModel.getSamplingTime()); + } + + @Test + public void testMemory() { + MemoryModel memoryModel = this.getMonitorService().memory( + SUT_HOST_NAME, PORT); + assertNotNull(memoryModel); + assertNotNull(memoryModel.getSamplingTime()); + } + + @Test + public void tesProcessor() { + ProcessorModel processorModel = this.getMonitorService().processor( + SUT_HOST_NAME, PORT); + assertNotNull(processorModel); + assertNotNull(processorModel.getSamplingTime()); + } + + @Test + public void testNetworkInterface() { + NetworkInterfaceModel networkInterfaceModel = this.getMonitorService() + .networkInterface(SUT_HOST_NAME, PORT); + assertNotNull(networkInterfaceModel); + assertNotNull(networkInterfaceModel.getSamplingTime()); + } + @Test + public void testMonitorModel(){ + MonitorMain monitorMain=this.getMonitorService().monitorModel(SUT_HOST_NAME, PORT); + assertNotNull(monitorMain); + } + @Test + public void testProcess(){ + ProcessModel processModel=this.getMonitorService().process(SUT_HOST_NAME, PORT); + assertNotNull(processModel); + } + +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_MonitorResultService.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_MonitorResultService.java new file mode 100644 index 00000000..940a6ff7 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_MonitorResultService.java @@ -0,0 +1,119 @@ +package org.bench4q.master.test.service; + +import static org.junit.Assert.*; + +import javax.xml.bind.JAXBException; + +import org.bench4q.master.domain.factory.TestPlanFactory; +import org.bench4q.master.domain.repository.TestPlanRepository; +import org.bench4q.master.domain.service.MonitorResultService; +import org.bench4q.master.exception.Bench4QException; +import org.bench4q.master.test.TestBase_MakeUpTestPlan; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_MonitorResultService extends TestBase_MakeUpTestPlan { + // private String monitor = "133.133.12.3"; + // private int port = 5556; + private MonitorResultService monitorResultService; + private TestPlanRepository testPlanRepository; + private TestPlanFactory testPlanFactory; + + public TestPlanFactory getTestPlanFactory() { + return testPlanFactory; + } + + @Autowired + public void setTestPlanFactory(TestPlanFactory testPlanFactory) { + this.testPlanFactory = testPlanFactory; + } + + private MonitorResultService getMonitorResultService() { + return monitorResultService; + } + + @Autowired + private void setMonitorResultService( + MonitorResultService monitorResultService) { + this.monitorResultService = monitorResultService; + } + + public TestPlanRepository getTestPlanRepository() { + return testPlanRepository; + } + + @Autowired + public void setTestPlanRepository(TestPlanRepository testPlanRepository) { + this.testPlanRepository = testPlanRepository; + } + + @Test + public void test() { + assertNotNull(this.getMonitorResultService()); + } + + @Before + public void makeUpTestPlanAndTestPlanScriptAndTestPlanScriptResult() + throws JAXBException { + prepareForTestPlanRunning(); + submitATestPlanWithOneScript(); + } + + @After + public void cleanUp() { + cleanUpForTestPlanRunning(); + } + + @Test + public void testLoadMemoryResults() throws InterruptedException, + Bench4QException {/* + * TestPlan testPlanInDomain = + * this.getTestPlanFactory().convertToDomain( + * this.getTestPlanRepository().getTestPlanBy( + * getTestPlanRunIdUuid())); + * this.getTestPlanEngine() + * .runWith(testPlanInDomain, user) + * assertEquals(TestPlanStatus.InRunning, + * testPlanInDomain.run()); Thread.sleep(1000); + * TestPlan testPlan = + * this.getTestPlanRepository().getTestPlanBy( + * getTestPlanRunIdUuid()); + * assertEquals(TestPlanStatus.InRunning, + * TestPlanStatus + * .valueOf(testPlan.getCurrentStatus())); + * Thread.sleep(4000); List + * logicalDiskModels = this + * .getMonitorResultService() + * .physicalDiskDiskResults + * (this.getTestPlanRunIdUuid(), monitor, port, + * 0).getPhysicalDiskModels(); List + * memoryModels = this .getMonitorResultService() + * .loadMemoryModels(this.getTestPlanRunIdUuid(), + * monitor, port, 0) .getMemoryModels(); + * List processorModels = this + * .getMonitorResultService() + * .loadProcessorModels(this.getTestPlanRunIdUuid(), + * monitor, port, 0).getProcessorModels(); + * List + * networkInterfaceModels = this + * .getMonitorResultService() + * .loadNetworkInterfaceModels + * (this.getTestPlanRunIdUuid(), monitor, port, + * 0).getModels(); assertEquals(1, + * processorModels.size()); + * assertTrue(processorModels.size() >= 1); + * assertTrue(logicalDiskModels.size() > 0); + * assertTrue(memoryModels.size() > 0); + * + * assertTrue(networkInterfaceModels.size() >= 1); + */ + } + +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_PluginService.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_PluginService.java new file mode 100644 index 00000000..e6e30c1e --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_PluginService.java @@ -0,0 +1,122 @@ +package org.bench4q.master.test.service; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +import javax.xml.bind.JAXBException; + +import org.apache.commons.io.FileUtils; +import org.bench4q.master.domain.service.PluginService; +import org.bench4q.master.exception.Bench4QException; +import org.bench4q.share.helper.MarshalHelper; +import org.bench4q.share.models.master.plugin.PluginModel; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import TestHelper.Test_PlunginHelper; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_PluginService { + + private PluginService pluginService; + + public PluginService getPluginService() { + return pluginService; + } + + private String nameForPlugin; + + @Autowired + public void setPluginService(PluginService pluginService) { + this.pluginService = pluginService; + } + + @Before + public void setUp() throws Bench4QException { + nameForPlugin = addPlugin(); + } + + @Test + public void testPluginModel() throws JAXBException, IOException { + File file = new File( + buildSavePath() + + System.getProperty("file.separator") + + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss") + .format(new Date()) + "plugin.xml"); + FileUtils.writeStringToFile( + file, + MarshalHelper.marshal(PluginModel.class, + Test_PlunginHelper.createOnePlugin())); + + } + + @Test + public void testGetMethodList() throws Bench4QException { + assertTrue(this.getPluginService().getPluginNameList().size() > 0); + int methodCount = this.getPluginService() + .getMethodNameInPlugin(nameForPlugin).size(); + assertEquals(1, methodCount); + } + + @Test + public void testLoadPluginList() throws Bench4QException { + int pluginCountBefore = this.getPluginService().getPluginNameList() + .size(); + String pluginName = addPlugin(); + System.out.println(this.getPluginService().getPluginNameList().size() + - pluginCountBefore); + Assert.assertTrue(this.getPluginService().getPluginNameList().size() == (pluginCountBefore + 1)); + + Assert.assertTrue(this.getPluginService().deletePlugin(pluginName)); + } + + @Test + public void getMethodParam() throws Bench4QException { + String methodName = this.getPluginService() + .getMethodNameInPlugin(nameForPlugin).get(0); + assertTrue(this.getPluginService().getMethodParamModelsInPlugin(nameForPlugin, + methodName).size()==2); + } + + @Test + public void testDeletePlugin() throws Bench4QException { + String pluginName = addPlugin(); + Assert.assertTrue(this.getPluginService().deletePlugin(pluginName)); + + } + + private String addPlugin() throws Bench4QException { + PluginModel plugin = Test_PlunginHelper.createOnePlugin(); + plugin.setName("test" + UUID.randomUUID()); + Assert.assertTrue(this.getPluginService().addPlugin(plugin)); + return plugin.getName(); + } + + @After + public void clear() throws Bench4QException { + this.getPluginService().deletePlugin(nameForPlugin); + } + + private String buildSavePath() { + String dirString = "GUI" + System.getProperty("file.separator") + + System.getProperty("file.separator"); + File dirFile = new File(dirString); + if (!dirFile.exists()) { + dirFile.mkdirs(); + } + return dirString; + } + +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_ReportService.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_ReportService.java new file mode 100644 index 00000000..4b881848 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_ReportService.java @@ -0,0 +1,41 @@ +package org.bench4q.master.test.service; + +import static org.junit.Assert.*; + +import java.util.UUID; + +import org.bench4q.master.report.ReportService; +import org.bench4q.master.test.TestBase_MakeUpTestPlan; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_ReportService extends TestBase_MakeUpTestPlan { + private ReportService reportService; + + private ReportService getReportService() { + return reportService; + } + + @Autowired + private void setReportService(ReportService reportService) { + this.reportService = reportService; + } + + @Test + public void testIsReportCreatedWhenActuallyNotCreated() { + submitATestPlanWithOneScript(); + assertFalse(this.getReportService().isReportCreated( + getTestPlanRunIdUuid())); + } + + @Test + public void testCreateReport() { + this.getReportService().createReport( + UUID.fromString("a75b14de-d99a-49ad-80b8-6ad6078ae726")); + } +} diff --git a/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_ScriptService.java b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_ScriptService.java new file mode 100644 index 00000000..3bc29f54 --- /dev/null +++ b/Bench4Q-Master/src/test/java/org/bench4q/master/test/service/Test_ScriptService.java @@ -0,0 +1,164 @@ +package org.bench4q.master.test.service; + +import static org.junit.Assert.*; + +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import javax.xml.bind.JAXBException; + +import org.bench4q.master.domain.entity.Script; +import org.bench4q.master.domain.entity.User; +import org.bench4q.master.domain.repository.UserRepository; +import org.bench4q.master.domain.service.ScriptService; +import org.bench4q.master.domain.service.UserService; +import org.bench4q.share.helper.MarshalHelper; +import org.bench4q.share.models.agent.RunScenarioModel; +import org.bench4q.share.models.agent.scriptrecord.PageModel; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:service-test-context.xml" }) +public class Test_ScriptService { + private ScriptService scriptService; + private UserService userService; + private UserRepository userRepository; + private User userForTest; + + private ScriptService getScriptService() { + return scriptService; + } + + @Autowired + private void setScriptService(ScriptService scriptService) { + this.scriptService = scriptService; + } + + private UserService getUserService() { + return userService; + } + + @Autowired + private void setUserService(UserService userService) { + this.userService = userService; + } + + private UserRepository getUserRepository() { + return userRepository; + } + + @Autowired + private void setUserRepository(UserRepository userRepository) { + this.userRepository = userRepository; + } + + private User getUserForTest() { + return userForTest; + } + + private void setUserForTest(User userForTest) { + this.userForTest = userForTest; + } + + @Test + public void testSaveScript() throws JAXBException { + User user = this.getUserRepository().getUser("test1"); + assertNotNull(user); + assertTrue(doSaveAScript(user)); + } + + private boolean doSaveAScript(User user) throws JAXBException { + return this.getScriptService().saveScript( + "ad", + user.getId(), + MarshalHelper.marshal(RunScenarioModel.class, + new RunScenarioModel())); + } + + @Before + public void prepare() { + this.getUserService().register("test1", "test1"); + this.setUserForTest(this.getUserRepository().getUser("test1")); + } + + @Test + public void testLoadScripts() throws JAXBException { + User user = this.getUserRepository().getUser("test1"); + assertNotNull(user); + assertTrue(this.getScriptService().saveScript( + "adef", + user.getId(), + MarshalHelper.marshal(RunScenarioModel.class, + new RunScenarioModel()))); + assertEquals(1, this.getScriptService().loadScripts(user).size()); + } + + @Test + public void testGetScript() throws JAXBException { + User user = this.getUserRepository().getUser("test1"); + doSaveAScript(user); + Script script = this.getScriptService().getScript( + getUploadScriptId(user)); + assertNotNull(script); + assertEquals("test1", script.getUser().getUserName()); + } + + private int getUploadScriptId(User user) { + return this.getScriptService().loadScripts(user).get(0).getId(); + } + + @Test + public void testQueryScriptsByCreateTime() throws JAXBException { + this.doSaveAScript(this.getUserForTest()); + List