diff --git a/testar/build.gradle b/testar/build.gradle index a5eeecf38..2f1a34317 100644 --- a/testar/build.gradle +++ b/testar/build.gradle @@ -103,6 +103,8 @@ dependencies { implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1' implementation group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.1' implementation group: 'com.orientechnologies', name: 'orientdb-graphdb', version: '3.0.34' + implementation 'com.jfoenix:jfoenix:8.0.10' + implementation 'org.jsoup:jsoup:1.13.1' implementation group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '5.10.0.202012080955-r' } diff --git a/testar/resources/jfx/Untitled.fxml b/testar/resources/jfx/Untitled.fxml new file mode 100644 index 000000000..f819b39ce --- /dev/null +++ b/testar/resources/jfx/Untitled.fxml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/dashboard.fxml b/testar/resources/jfx/dashboard.fxml new file mode 100644 index 000000000..c91abb538 --- /dev/null +++ b/testar/resources/jfx/dashboard.fxml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/filter_button.fxml b/testar/resources/jfx/filter_button.fxml new file mode 100644 index 000000000..5e268a640 --- /dev/null +++ b/testar/resources/jfx/filter_button.fxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/flash_feedback.fxml b/testar/resources/jfx/flash_feedback.fxml new file mode 100644 index 000000000..87e89b62f --- /dev/null +++ b/testar/resources/jfx/flash_feedback.fxml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/testar/resources/jfx/icons/add.png b/testar/resources/jfx/icons/add.png new file mode 100644 index 000000000..f03edd454 Binary files /dev/null and b/testar/resources/jfx/icons/add.png differ diff --git a/testar/resources/jfx/icons/attach.png b/testar/resources/jfx/icons/attach.png new file mode 100644 index 000000000..6e8992d20 Binary files /dev/null and b/testar/resources/jfx/icons/attach.png differ diff --git a/testar/resources/jfx/icons/auto.png b/testar/resources/jfx/icons/auto.png new file mode 100644 index 000000000..b5304cb7f Binary files /dev/null and b/testar/resources/jfx/icons/auto.png differ diff --git a/testar/resources/jfx/icons/back.png b/testar/resources/jfx/icons/back.png new file mode 100644 index 000000000..539f6583a Binary files /dev/null and b/testar/resources/jfx/icons/back.png differ diff --git a/testar/resources/jfx/icons/close.png b/testar/resources/jfx/icons/close.png new file mode 100644 index 000000000..c7e27e458 Binary files /dev/null and b/testar/resources/jfx/icons/close.png differ diff --git a/testar/resources/jfx/icons/close_white.png b/testar/resources/jfx/icons/close_white.png new file mode 100644 index 000000000..6f52e6b9b Binary files /dev/null and b/testar/resources/jfx/icons/close_white.png differ diff --git a/testar/resources/jfx/icons/filter.png b/testar/resources/jfx/icons/filter.png new file mode 100644 index 000000000..a9a9f0c16 Binary files /dev/null and b/testar/resources/jfx/icons/filter.png differ diff --git a/testar/resources/jfx/icons/general.png b/testar/resources/jfx/icons/general.png new file mode 100644 index 000000000..6d787b527 Binary files /dev/null and b/testar/resources/jfx/icons/general.png differ diff --git a/testar/resources/jfx/icons/home.png b/testar/resources/jfx/icons/home.png new file mode 100644 index 000000000..6e6dabc02 Binary files /dev/null and b/testar/resources/jfx/icons/home.png differ diff --git a/testar/resources/jfx/icons/info.png b/testar/resources/jfx/icons/info.png new file mode 100644 index 000000000..71c457848 Binary files /dev/null and b/testar/resources/jfx/icons/info.png differ diff --git a/testar/resources/jfx/icons/misc.png b/testar/resources/jfx/icons/misc.png new file mode 100644 index 000000000..6cf50a70e Binary files /dev/null and b/testar/resources/jfx/icons/misc.png differ diff --git a/testar/resources/jfx/icons/rec.png b/testar/resources/jfx/icons/rec.png new file mode 100644 index 000000000..4d1417c2b Binary files /dev/null and b/testar/resources/jfx/icons/rec.png differ diff --git a/testar/resources/jfx/icons/replay.png b/testar/resources/jfx/icons/replay.png new file mode 100644 index 000000000..4bbcefc41 Binary files /dev/null and b/testar/resources/jfx/icons/replay.png differ diff --git a/testar/resources/jfx/icons/settings.png b/testar/resources/jfx/icons/settings.png new file mode 100644 index 000000000..eb0072af8 Binary files /dev/null and b/testar/resources/jfx/icons/settings.png differ diff --git a/testar/resources/jfx/icons/settings_state.fxml b/testar/resources/jfx/icons/settings_state.fxml new file mode 100644 index 000000000..9e01a2593 --- /dev/null +++ b/testar/resources/jfx/icons/settings_state.fxml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/icons/settings_white_24dp.svg b/testar/resources/jfx/icons/settings_white_24dp.svg new file mode 100644 index 000000000..7074fa8ba --- /dev/null +++ b/testar/resources/jfx/icons/settings_white_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/testar/resources/jfx/icons/source.png b/testar/resources/jfx/icons/source.png new file mode 100644 index 000000000..7ed686503 Binary files /dev/null and b/testar/resources/jfx/icons/source.png differ diff --git a/testar/resources/jfx/icons/spy.png b/testar/resources/jfx/icons/spy.png new file mode 100644 index 000000000..6a8526dd1 Binary files /dev/null and b/testar/resources/jfx/icons/spy.png differ diff --git a/testar/resources/jfx/icons/state.png b/testar/resources/jfx/icons/state.png new file mode 100644 index 000000000..882508ff0 Binary files /dev/null and b/testar/resources/jfx/icons/state.png differ diff --git a/testar/resources/jfx/icons/time.png b/testar/resources/jfx/icons/time.png new file mode 100644 index 000000000..5daa1ddaf Binary files /dev/null and b/testar/resources/jfx/icons/time.png differ diff --git a/testar/resources/jfx/icons/view.png b/testar/resources/jfx/icons/view.png new file mode 100644 index 000000000..51f57b31d Binary files /dev/null and b/testar/resources/jfx/icons/view.png differ diff --git a/testar/resources/jfx/icons/whitebox.png b/testar/resources/jfx/icons/whitebox.png new file mode 100644 index 000000000..51d0a38ad Binary files /dev/null and b/testar/resources/jfx/icons/whitebox.png differ diff --git a/testar/resources/jfx/lang_header.fxml b/testar/resources/jfx/lang_header.fxml new file mode 100644 index 000000000..7b36da6b4 --- /dev/null +++ b/testar/resources/jfx/lang_header.fxml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/lang_item.fxml b/testar/resources/jfx/lang_item.fxml new file mode 100644 index 000000000..8e9d99fed --- /dev/null +++ b/testar/resources/jfx/lang_item.fxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/testar/resources/jfx/logos/ing.png b/testar/resources/jfx/logos/ing.png new file mode 100644 index 000000000..ae176c208 Binary files /dev/null and b/testar/resources/jfx/logos/ing.png differ diff --git a/testar/resources/jfx/logos/marviq.png b/testar/resources/jfx/logos/marviq.png new file mode 100644 index 000000000..dccf0fdee Binary files /dev/null and b/testar/resources/jfx/logos/marviq.png differ diff --git a/testar/resources/jfx/logos/open_university.png b/testar/resources/jfx/logos/open_university.png new file mode 100644 index 000000000..6905e5feb Binary files /dev/null and b/testar/resources/jfx/logos/open_university.png differ diff --git a/testar/resources/jfx/logos/philips.png b/testar/resources/jfx/logos/philips.png new file mode 100644 index 000000000..28b9e71ae Binary files /dev/null and b/testar/resources/jfx/logos/philips.png differ diff --git a/testar/resources/jfx/logos/sogeti.png b/testar/resources/jfx/logos/sogeti.png new file mode 100644 index 000000000..269c3d394 Binary files /dev/null and b/testar/resources/jfx/logos/sogeti.png differ diff --git a/testar/resources/jfx/main.fxml b/testar/resources/jfx/main.fxml new file mode 100644 index 000000000..c761571ce --- /dev/null +++ b/testar/resources/jfx/main.fxml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/testar/resources/jfx/misc.fxml b/testar/resources/jfx/misc.fxml new file mode 100644 index 000000000..8c5e62e5c --- /dev/null +++ b/testar/resources/jfx/misc.fxml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/testar/resources/jfx/new_tag.fxml b/testar/resources/jfx/new_tag.fxml new file mode 100644 index 000000000..130177187 --- /dev/null +++ b/testar/resources/jfx/new_tag.fxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/testar/resources/jfx/settings.fxml b/testar/resources/jfx/settings.fxml new file mode 100644 index 000000000..6865f84dd --- /dev/null +++ b/testar/resources/jfx/settings.fxml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_child.fxml b/testar/resources/jfx/settings_child.fxml new file mode 100644 index 000000000..f92a5d421 --- /dev/null +++ b/testar/resources/jfx/settings_child.fxml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_filter.fxml b/testar/resources/jfx/settings_filter.fxml new file mode 100644 index 000000000..0156e2511 --- /dev/null +++ b/testar/resources/jfx/settings_filter.fxml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_general.fxml b/testar/resources/jfx/settings_general.fxml new file mode 100644 index 000000000..c2d856ecb --- /dev/null +++ b/testar/resources/jfx/settings_general.fxml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_git.fxml b/testar/resources/jfx/settings_git.fxml new file mode 100644 index 000000000..7cbea40e2 --- /dev/null +++ b/testar/resources/jfx/settings_git.fxml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_misc.fxml b/testar/resources/jfx/settings_misc.fxml new file mode 100644 index 000000000..4a8b4d3c8 --- /dev/null +++ b/testar/resources/jfx/settings_misc.fxml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_misc_old.fxml b/testar/resources/jfx/settings_misc_old.fxml new file mode 100644 index 000000000..c72313502 --- /dev/null +++ b/testar/resources/jfx/settings_misc_old.fxml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_new.fxml b/testar/resources/jfx/settings_new.fxml new file mode 100644 index 000000000..6e67aa539 --- /dev/null +++ b/testar/resources/jfx/settings_new.fxml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_repo.fxml b/testar/resources/jfx/settings_repo.fxml new file mode 100644 index 000000000..266d32022 --- /dev/null +++ b/testar/resources/jfx/settings_repo.fxml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_section.fxml b/testar/resources/jfx/settings_section.fxml new file mode 100644 index 000000000..961f95ae0 --- /dev/null +++ b/testar/resources/jfx/settings_section.fxml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_sonar.fxml b/testar/resources/jfx/settings_sonar.fxml new file mode 100644 index 000000000..aeef7f03a --- /dev/null +++ b/testar/resources/jfx/settings_sonar.fxml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_sonar_project.fxml b/testar/resources/jfx/settings_sonar_project.fxml new file mode 100644 index 000000000..eda7b373f --- /dev/null +++ b/testar/resources/jfx/settings_sonar_project.fxml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_sonar_service.fxml b/testar/resources/jfx/settings_sonar_service.fxml new file mode 100644 index 000000000..634924a4b --- /dev/null +++ b/testar/resources/jfx/settings_sonar_service.fxml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_sonarqube.fxml b/testar/resources/jfx/settings_sonarqube.fxml new file mode 100644 index 000000000..f99d98afb --- /dev/null +++ b/testar/resources/jfx/settings_sonarqube.fxml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_startup.fxml b/testar/resources/jfx/settings_startup.fxml new file mode 100644 index 000000000..a545b7da2 --- /dev/null +++ b/testar/resources/jfx/settings_startup.fxml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_state.fxml b/testar/resources/jfx/settings_state.fxml new file mode 100644 index 000000000..2785a55d6 --- /dev/null +++ b/testar/resources/jfx/settings_state.fxml @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_time.fxml b/testar/resources/jfx/settings_time.fxml new file mode 100644 index 000000000..f73934cf5 --- /dev/null +++ b/testar/resources/jfx/settings_time.fxml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_web.fxml b/testar/resources/jfx/settings_web.fxml new file mode 100644 index 000000000..673d679ea --- /dev/null +++ b/testar/resources/jfx/settings_web.fxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/settings_widgets.fxml b/testar/resources/jfx/settings_widgets.fxml new file mode 100644 index 000000000..3246e34f8 --- /dev/null +++ b/testar/resources/jfx/settings_widgets.fxml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/tag.fxml b/testar/resources/jfx/tag.fxml new file mode 100644 index 000000000..159f40771 --- /dev/null +++ b/testar/resources/jfx/tag.fxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + diff --git a/testar/resources/jfx/whitebox_test_status.fxml b/testar/resources/jfx/whitebox_test_status.fxml new file mode 100644 index 000000000..68f96c452 --- /dev/null +++ b/testar/resources/jfx/whitebox_test_status.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testar/resources/logos/ing.png b/testar/resources/logos/ing.png new file mode 100644 index 000000000..ae176c208 Binary files /dev/null and b/testar/resources/logos/ing.png differ diff --git a/testar/resources/logos/marviq.png b/testar/resources/logos/marviq.png new file mode 100644 index 000000000..dccf0fdee Binary files /dev/null and b/testar/resources/logos/marviq.png differ diff --git a/testar/resources/logos/open_university.png b/testar/resources/logos/open_university.png new file mode 100644 index 000000000..6905e5feb Binary files /dev/null and b/testar/resources/logos/open_university.png differ diff --git a/testar/resources/logos/philips.png b/testar/resources/logos/philips.png new file mode 100644 index 000000000..28b9e71ae Binary files /dev/null and b/testar/resources/logos/philips.png differ diff --git a/testar/resources/logos/sogeti.png b/testar/resources/logos/sogeti.png new file mode 100644 index 000000000..269c3d394 Binary files /dev/null and b/testar/resources/logos/sogeti.png differ diff --git a/testar/resources/settings/01_desktop_generic_pure_random/test.settings b/testar/resources/settings/01_desktop_generic_pure_random/test.settings index 906e17297..9314d48f5 100644 --- a/testar/resources/settings/01_desktop_generic_pure_random/test.settings +++ b/testar/resources/settings/01_desktop_generic_pure_random/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # diff --git a/testar/resources/settings/02_webdriver_parabank/test.settings b/testar/resources/settings/02_webdriver_parabank/test.settings index b246ef37d..c22eb3163 100644 --- a/testar/resources/settings/02_webdriver_parabank/test.settings +++ b/testar/resources/settings/02_webdriver_parabank/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # diff --git a/testar/resources/settings/desktop_generic/test.settings b/testar/resources/settings/desktop_generic/test.settings index e51c26110..c74cacbd7 100644 --- a/testar/resources/settings/desktop_generic/test.settings +++ b/testar/resources/settings/desktop_generic/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # diff --git a/testar/resources/settings/desktop_generic_action_selection/test.settings b/testar/resources/settings/desktop_generic_action_selection/test.settings index 26f038b13..110236332 100644 --- a/testar/resources/settings/desktop_generic_action_selection/test.settings +++ b/testar/resources/settings/desktop_generic_action_selection/test.settings @@ -6,6 +6,14 @@ Mode = Generate +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_generic_all_features/test.settings b/testar/resources/settings/desktop_generic_all_features/test.settings index 7c4268929..ce69890b9 100644 --- a/testar/resources/settings/desktop_generic_all_features/test.settings +++ b/testar/resources/settings/desktop_generic_all_features/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_generic_json/test.settings b/testar/resources/settings/desktop_generic_json/test.settings index e70f2a889..d5aa0d3ee 100644 --- a/testar/resources/settings/desktop_generic_json/test.settings +++ b/testar/resources/settings/desktop_generic_json/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_generic_statemodel/test.settings b/testar/resources/settings/desktop_generic_statemodel/test.settings index aa84ae8f5..d6bde106a 100644 --- a/testar/resources/settings/desktop_generic_statemodel/test.settings +++ b/testar/resources/settings/desktop_generic_statemodel/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = true + ################################################################# # Connect to the System Under Test (SUT) # @@ -150,4 +158,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_qlearning/test.settings b/testar/resources/settings/desktop_qlearning/test.settings index 99d721aad..a9fd5adbd 100644 --- a/testar/resources/settings/desktop_qlearning/test.settings +++ b/testar/resources/settings/desktop_qlearning/test.settings @@ -6,6 +6,14 @@ Mode = Generate +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = true + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_simple_stategraph/test.settings b/testar/resources/settings/desktop_simple_stategraph/test.settings index 8d5725813..bb093e450 100644 --- a/testar/resources/settings/desktop_simple_stategraph/test.settings +++ b/testar/resources/settings/desktop_simple_stategraph/test.settings @@ -6,6 +6,14 @@ Mode = Generate +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = true + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_simple_stategraph_eye/test.settings b/testar/resources/settings/desktop_simple_stategraph_eye/test.settings index 76bcc36e5..b61efb8ac 100644 --- a/testar/resources/settings/desktop_simple_stategraph_eye/test.settings +++ b/testar/resources/settings/desktop_simple_stategraph_eye/test.settings @@ -6,6 +6,14 @@ Mode = Generate +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = true + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_simple_stategraph_sikulix/test.settings b/testar/resources/settings/desktop_simple_stategraph_sikulix/test.settings index 190218781..ec64647c1 100644 --- a/testar/resources/settings/desktop_simple_stategraph_sikulix/test.settings +++ b/testar/resources/settings/desktop_simple_stategraph_sikulix/test.settings @@ -6,6 +6,14 @@ Mode = Generate +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = true + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/desktop_swingset2/test.settings b/testar/resources/settings/desktop_swingset2/test.settings index 0ab650cbd..623faefdf 100644 --- a/testar/resources/settings/desktop_swingset2/test.settings +++ b/testar/resources/settings/desktop_swingset2/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # @@ -149,4 +157,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/webdriver_detect_similarity/test.settings b/testar/resources/settings/webdriver_detect_similarity/test.settings index 4881ab070..17cda38da 100644 --- a/testar/resources/settings/webdriver_detect_similarity/test.settings +++ b/testar/resources/settings/webdriver_detect_similarity/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # diff --git a/testar/resources/settings/webdriver_generic/test.settings b/testar/resources/settings/webdriver_generic/test.settings index 24e8f238e..ef0dad83b 100644 --- a/testar/resources/settings/webdriver_generic/test.settings +++ b/testar/resources/settings/webdriver_generic/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # @@ -186,3 +194,14 @@ TestGenerator = random MaxReward = 9999999 Discount = .95 RefreshSpyCanvas = 1.0 + +################################################################# +# Whitebox test settings +################################################################# + +SonarDockerize = true +SonarProjectName = Demo +SonarProjectKey = demo +GitUrl = https://github.com/ICTU/quality-time +GitAuthRequired = false + diff --git a/testar/resources/settings/webdriver_gwt/test.settings b/testar/resources/settings/webdriver_gwt/test.settings index f21537367..caab2df45 100644 --- a/testar/resources/settings/webdriver_gwt/test.settings +++ b/testar/resources/settings/webdriver_gwt/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # diff --git a/testar/resources/settings/webdriver_spy_custom/test.settings b/testar/resources/settings/webdriver_spy_custom/test.settings index de73b157c..5d051ebe4 100644 --- a/testar/resources/settings/webdriver_spy_custom/test.settings +++ b/testar/resources/settings/webdriver_spy_custom/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # diff --git a/testar/resources/settings/webdriver_statemodel/test.settings b/testar/resources/settings/webdriver_statemodel/test.settings index 5ef1cd1b7..999180dd3 100644 --- a/testar/resources/settings/webdriver_statemodel/test.settings +++ b/testar/resources/settings/webdriver_statemodel/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = true + ################################################################# # Connect to the System Under Test (SUT) # @@ -189,3 +197,9 @@ TestGenerator = random MaxReward = 9999999 Discount = .95 RefreshSpyCanvas = 1.0 + +SonarDockerize = true +SonarProjectName = Demo +SonarProjectKey = demo +GitUrl = https://github.com/crystal-lang/crystal +GitAuthRequired = false diff --git a/testar/resources/settings/winapi_web_generic/test.settings b/testar/resources/settings/winapi_web_generic/test.settings index 5e8529869..21778f510 100644 --- a/testar/resources/settings/winapi_web_generic/test.settings +++ b/testar/resources/settings/winapi_web_generic/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/resources/settings/winapi_web_one_drive/test.settings b/testar/resources/settings/winapi_web_one_drive/test.settings index ea6e46654..a2dcc4c30 100644 --- a/testar/resources/settings/winapi_web_one_drive/test.settings +++ b/testar/resources/settings/winapi_web_one_drive/test.settings @@ -6,6 +6,14 @@ Mode = Spy +################################################################# +# State model enabled +# +# Only applicable for StateGraph, StatdModel and QLearning +################################################################# + +StateModelEnabled = false + ################################################################# # Connect to the System Under Test (SUT) # @@ -138,4 +146,4 @@ VisualizeActions = false VisualizeSelectedAction = true TestGenerator = random MaxReward = 9999999 -Discount = .95 \ No newline at end of file +Discount = .95 diff --git a/testar/src/es/upv/staq/testar/FlashFeedbackOld.java b/testar/src/es/upv/staq/testar/FlashFeedbackOld.java new file mode 100644 index 000000000..f0037fb2e --- /dev/null +++ b/testar/src/es/upv/staq/testar/FlashFeedbackOld.java @@ -0,0 +1,85 @@ +/*************************************************************************************************** +* +* Copyright (c) 2015, 2016, 2017, 2018 Universitat Politecnica de Valencia - www.upv.es +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************************************/ + + +package es.upv.staq.testar; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Label; + +import javax.swing.JDialog; +import javax.swing.JFrame; + +/** + * Displays a short-time flash message for feedback. + * + * @author Urko Rueda Molina (alias: urueda) + * + */ + public class FlashFeedbackOld extends JDialog implements Runnable { + + private static final long serialVersionUID = -3851564540655407657L; + + private static int FLASH_DURATION = 1000; // ms + + /** + * @param title Non-null and non empty text. + */ + private FlashFeedbackOld(String title) { + super((JFrame)null, title, false); + this.setType(Type.POPUP); + this.setUndecorated(true); + Label msg = new Label(title); + msg.setBackground(Color.BLACK); + msg.setForeground(Color.WHITE); + this.add(msg); + int dimW = (title.length() + 1) * 12; + this.setSize(new Dimension(Math.min(dimW, 512), 32)); + this.setOpacity(0.75f); + } + + public static void flash(String title, int duration){ + if(duration>1000) FLASH_DURATION = duration; + new FlashFeedbackOld(title).run(); + } + + @Override + public void run() { + this.setVisible(true); + synchronized(this){ + try{ + this.wait(FLASH_DURATION); + } catch (java.lang.InterruptedException e){} + } + this.setVisible(false); + this.dispose(); + } + +} diff --git a/testar/src/nl/ou/testar/jfx/MainController.java b/testar/src/nl/ou/testar/jfx/MainController.java new file mode 100644 index 000000000..e925a1455 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/MainController.java @@ -0,0 +1,122 @@ +package nl.ou.testar.jfx; + +import javafx.scene.Parent; +import javafx.scene.layout.AnchorPane; +import javafx.stage.Stage; +import nl.ou.testar.jfx.core.NavigationController; +import nl.ou.testar.jfx.core.NavigationDelegate; +import nl.ou.testar.jfx.core.ViewController; +import nl.ou.testar.jfx.dashboard.DashboardController; +import nl.ou.testar.jfx.misc.MiscController; +import nl.ou.testar.jfx.settings.SettingsController; + +import javafx.scene.control.*; +import org.testar.monkey.Settings; + +public class MainController extends ViewController { + + enum Mode { + HOME, SETTINGS, MISC + } + + private Mode mode; + private String settingsPath; + + private DashboardController dashboardController; + private SettingsController settingsController; + private MiscController miscController; + + private Stage stage = null; + + public DashboardController getDashboardController() { + return dashboardController; + } + + public MainController(Settings settings, String settingsPath) { + super("Testar", "jfx/main.fxml", settings); + this.settingsPath = settingsPath; + dashboardController = new DashboardController(settings, settingsPath); + settingsController = new SettingsController(settings, settingsPath); + miscController = new MiscController("Misc", settings); + } + + private void setupMode(Parent view, Mode mode) { + + if (mode != this.mode) { +// final Label titleLabel = (Label) view.lookup("#titleLabel"); +// final Button btnBack = (Button) view.lookup("#btnBack"); + +// final BorderPane contentPane = (BorderPane) view.lookup("#contentPane"); + final AnchorPane contentPane = (AnchorPane) view.lookup("#contentPane"); + ViewController targetController; + switch (mode) { + case SETTINGS: + targetController = settingsController; + break; + case MISC: + targetController = miscController; + break; + default: //HOME + targetController = dashboardController; + break; + } + final NavigationController navigationController = new NavigationController(targetController); + navigationController.startWithDelegate(new NavigationDelegate() { + @Override + public void onViewControllerActivated(ViewController viewController, Parent view) { +// titleLabel.setText(viewController.getTitle()); + contentPane.getChildren().clear(); + contentPane.getChildren().add(view); + AnchorPane.setLeftAnchor(view, 0.0); + AnchorPane.setTopAnchor(view, 0.0); + AnchorPane.setRightAnchor(view, 0.0); + AnchorPane.setBottomAnchor(view, 0.0); + + if (stage != null) { + double width = stage.getWidth(); + double height = stage.getHeight(); + + view.setVisible(false); + stage.sizeToScene(); + stage.setWidth(Math.max(width, stage.getWidth())); + stage.setHeight(Math.max(height, stage.getHeight())); + view.setVisible(true); + } + } + }); + +// btnBack.setOnAction(event -> { +// navigationController.navigateBack(); +// }); + + this.mode = mode; + } + } + + @Override + public void viewDidLoad(Parent view) { + Button btnHome = (Button) view.lookup("#btnHome"); + Button btnSettings = (Button) view.lookup("#btnSettings"); + Button btnMisc = (Button) view.lookup("#btnMisc"); + + btnHome.setOnAction(event -> { + setupMode(view, Mode.HOME); + + }); + + btnSettings.setOnAction(event -> { + setupMode(view, Mode.SETTINGS); + }); + +// btnMisc.setOnAction(event -> { +// setupMode(view, Mode.MISC); +// }); + + setupMode(view, Mode.HOME); + } + + @Override + public void viewDidAppear(Parent view) { + stage = (Stage) view.getScene().getWindow(); + } +} diff --git a/testar/src/nl/ou/testar/jfx/MainControllerDelegate.java b/testar/src/nl/ou/testar/jfx/MainControllerDelegate.java new file mode 100644 index 000000000..65c3338e6 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/MainControllerDelegate.java @@ -0,0 +1,7 @@ +package nl.ou.testar.jfx; + +import javafx.scene.Parent; + +public interface MainControllerDelegate { + void setContentView(Parent contentView); +} diff --git a/testar/src/nl/ou/testar/jfx/WhiteboxTestStatus.java b/testar/src/nl/ou/testar/jfx/WhiteboxTestStatus.java new file mode 100644 index 000000000..ec8e19f6b --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/WhiteboxTestStatus.java @@ -0,0 +1,180 @@ +package nl.ou.testar.jfx; + +import javafx.application.Platform; +import javafx.event.EventHandler; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.control.ProgressBar; +import javafx.scene.input.KeyEvent; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import nl.ou.testar.jfx.dashboard.DashboardDelegate; +import org.eclipse.jgit.lib.ProgressMonitor; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Settings; +import org.testar.settingsdialog.codeanalysis.CodeAnalysisService; +import org.testar.settingsdialog.codeanalysis.CodeAnalysisServiceImpl; +import org.testar.settingsdialog.codeanalysis.RepositoryLanguage; +import org.testar.settingsdialog.codeanalysis.RepositoryLanguageComposition; +import org.testar.settingsdialog.vcs.GitCredentials; +import org.testar.settingsdialog.vcs.GitService; +import org.testar.settingsdialog.vcs.GitServiceImpl; + +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.file.Path; + +public class WhiteboxTestStatus implements ProgressMonitor { + + private Parent view; + private Stage mainStage; + + private Label stageLabel; + private Label statusLabel; + private ProgressBar progressBar; + private VBox contentBox; + + private int currentProgress; + private int totalProgress; + + private DashboardDelegate dashboardDelegate; + + private String projectName; + private String projectKey; + private GitCredentials gitCredentials; + + private final static int HEADER_HEIGHT = 56; + private final static int ITEM_HEIGHT = 44; + + private final CodeAnalysisService codeAnalysisService = new CodeAnalysisServiceImpl(); + + public void start(Stage stage, Settings settings) throws IOException { + mainStage = stage; + mainStage.hide(); + Stage whiteboxStage = new Stage(StageStyle.UNDECORATED); + + FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/whitebox_test_status.fxml")); + view = loader.load(); + whiteboxStage.setScene(new Scene(view)); + whiteboxStage.show(); + + stageLabel = (Label) view.lookup("#procStage"); + statusLabel = (Label) view.lookup("#procStatus"); + progressBar = (ProgressBar) view.lookup("#procProgressBar"); + contentBox = (VBox) view.lookup("#contentBox"); + + // Clone GIT repository + + final GitService gitService = new GitServiceImpl(); + final String repositoryUrl = settings.get(ConfigTags.GitUrl); + + final String branchName = settings.get(ConfigTags.GitBranch, null); + + projectName = settings.get(ConfigTags.SonarProjectName, "Demo"); + projectKey = settings.get(ConfigTags.SonarProjectKey, "demo"); + + if (settings.get(ConfigTags.GitAuthRequired, false)) { + gitCredentials = new GitCredentials(settings.get(ConfigTags.GitUsername), settings.get(ConfigTags.GitToken)); + } + + stageLabel.setText("Cloning repository"); + new Thread(() -> { + Path repositoryPath; + if (gitCredentials == null) { + repositoryPath = gitService.cloneRepository(repositoryUrl, this, branchName); + } else { + repositoryPath = gitService.cloneRepository(repositoryUrl, gitCredentials, this, branchName); + } + System.out.println("...done"); + + RepositoryLanguageComposition composition = codeAnalysisService.scanRepository(repositoryPath); + + Platform.runLater(() -> { + try { + FXMLLoader headerLoader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/lang_header.fxml")); + contentBox.getChildren().add(headerLoader.load()); + whiteboxStage.setHeight(whiteboxStage.getHeight() + HEADER_HEIGHT); + for (RepositoryLanguage language : composition.getRepositoryLanguages()) { + whiteboxStage.setHeight(whiteboxStage.getHeight() + ITEM_HEIGHT); + FXMLLoader itemLoader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/lang_item.fxml")); + Parent itemView = itemLoader.load(); + Label itemLabel = (Label) itemView.lookup("#lang"); + ProgressBar itemProgressBar = (ProgressBar) itemView.lookup("#ratio"); + BigDecimal percentage = language.getPercentage(); + itemLabel.setText(String.format("%d%% %s", percentage.intValue(), language.getSupportedLanguage().getName())); + itemProgressBar.setProgress(0.01 * percentage.doubleValue()); + contentBox.getChildren().add(itemView); + } + } catch (IOException e) { + final Alert alert = new Alert(Alert.AlertType.ERROR, "Cannot start code analysis\n" + e.getMessage()); + alert.show(); + stop(); + e.printStackTrace(); + } + + stageLabel.setText("All done"); + statusLabel.setText("Press any key to close"); + progressBar.setVisible(false); + + whiteboxStage.getScene().addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler() { + @Override + public void handle(KeyEvent event) { + stop(); + } + }); + }); + }).start(); + } + + @Override + public void start(int totalTasks) { + } + + @Override + public void beginTask(String title, int totalWork) { + System.out.println("Process started"); + Platform.runLater(() -> { + statusLabel.setText(title); + progressBar.setProgress(0); + currentProgress = 0; + totalProgress = totalWork; + }); + } + + @Override + public void update(int completed) { + Platform.runLater(() -> { + currentProgress += completed; + if (totalProgress > 0) { + progressBar.setProgress((double)currentProgress / totalProgress); + } + }); + } + + @Override + public void endTask() { + System.out.println("Process finished"); + Platform.runLater(() -> { + progressBar.setProgress(1.0); + }); + } + + @Override + public boolean isCancelled() { + return false; + } + + public void stop() { + if (view == null) { + return; + } + + final Stage stage = (Stage) view.getScene().getWindow(); + stage.close(); + mainStage.show(); + } +} diff --git a/testar/src/nl/ou/testar/jfx/controls/FlashFeedback.java b/testar/src/nl/ou/testar/jfx/controls/FlashFeedback.java new file mode 100644 index 000000000..67ea45a47 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/controls/FlashFeedback.java @@ -0,0 +1,28 @@ +package nl.ou.testar.jfx.controls; + +import javafx.animation.Animation; +import javafx.animation.FadeTransition; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Label; +import javafx.util.Duration; + +import java.io.IOException; + +public class FlashFeedback extends Parent { + public FlashFeedback(String message) { + FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/flash_feedback.fxml")); + try { + Parent view = loader.load(); + Label messageLabel = (Label) view.lookup("#messageText"); + messageLabel.setText(message); + + FadeTransition fadeTransition = new FadeTransition(Duration.seconds(1.0), messageLabel); + fadeTransition.setFromValue(1.0); + fadeTransition.setToValue(0.0); + fadeTransition.setCycleCount(Animation.INDEFINITE); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/testar/src/nl/ou/testar/jfx/controls/TagControl.java b/testar/src/nl/ou/testar/jfx/controls/TagControl.java new file mode 100644 index 000000000..5de11b8b0 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/controls/TagControl.java @@ -0,0 +1,51 @@ +package nl.ou.testar.jfx.controls; + +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; + +import java.io.IOException; + +public class TagControl extends Parent { + + public interface Delegate { + void onClose(); + } + + private Delegate delegate; + final String tag; + + public Delegate getDelegate() { + return delegate; + } + + public void setDelegate(Delegate delegate) { + this.delegate = delegate; + } + + public String getTag() { + return tag; + } + + public TagControl(String tag) { + this.tag = tag; + FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/tag.fxml")); + try { + Parent view = loader.load(); + Label tagLabel = (Label) view.lookup("#tagLabel"); + tagLabel.setText(tag); + Button btnClose = (Button) view.lookup("#btnClose"); + btnClose.setOnAction(event -> { + if (delegate != null) { + delegate.onClose(); + } + }); + + getChildren().add(view); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/testar/src/nl/ou/testar/jfx/controls/TagInput.java b/testar/src/nl/ou/testar/jfx/controls/TagInput.java new file mode 100644 index 000000000..0183788e6 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/controls/TagInput.java @@ -0,0 +1,53 @@ +package nl.ou.testar.jfx.controls; + +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyCode; + +import java.io.IOException; + +public class TagInput extends Parent { + public interface Delegate { + void tagTyped(String tag); + } + + private TextField tagInputField; + private Delegate delegate; + + public Delegate getDelegate() { + return delegate; + } + + public void setDelegate(Delegate delegate) { + this.delegate = delegate; + } + + public TagInput() { + FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/new_tag.fxml")); + try { + Parent view = loader.load(); + tagInputField = (TextField) view.lookup("#newTagInput"); + tagInputField.textProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue.matches("\\w*")) { + tagInputField.setText(newValue.replaceAll("\\W+", "")); + } + }); + tagInputField.setOnKeyPressed(event -> { + if(event.getCode().equals(KeyCode.ENTER)) { + final String tag = tagInputField.getText(); + if (delegate != null && tag.length() > 0) { + delegate.tagTyped(tag); + } + } + }); + getChildren().add(view); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void clear() { + tagInputField.clear(); + } +} diff --git a/testar/src/nl/ou/testar/jfx/core/NavigationController.java b/testar/src/nl/ou/testar/jfx/core/NavigationController.java new file mode 100644 index 000000000..b06d01192 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/core/NavigationController.java @@ -0,0 +1,107 @@ +package nl.ou.testar.jfx.core; + +import javafx.scene.Parent; + +import java.io.IOException; +import java.util.Stack; + +public class NavigationController { + + private NavigationDelegate delegate; + private Stack viewControllerStack = new Stack<>(); + private ViewController currentViewController; + private ViewController rootViewController; + + public NavigationController(ViewController rootViewController) { + this.currentViewController = rootViewController; + this.rootViewController = rootViewController; + rootViewController.setNavigationController(this); + } + + public NavigationDelegate getDelegate() { + return delegate; + } + + void setDelegate(NavigationDelegate delegate) { + this.delegate = delegate; + } + + public void startWithDelegate(NavigationDelegate delegate) { + this.delegate = delegate; + try { + Parent view = currentViewController.obtainView(); + currentViewController.viewWillAppear(view); + delegate.onViewControllerActivated(currentViewController, view); + currentViewController.viewDidAppear(view); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public ViewController getRootViewController() { + return rootViewController; + } + + public ViewController getCurrentViewController() { + return currentViewController; + } + + public boolean navigateTo(ViewController viewController, Boolean pushToStack) { + //TODO: delegate shouldn't be nil + if (!currentViewController.checkBeforeExit()) { + return false; + } + + try { + Parent view = viewController.obtainView(); + ViewController previousViewController = currentViewController; + previousViewController.viewWillDisappear(); + if (pushToStack) { + viewControllerStack.push(currentViewController); + } + currentViewController = viewController; + viewController.setNavigationController(this); + + currentViewController.viewWillAppear(view); + delegate.onViewControllerActivated(currentViewController, view); + previousViewController.viewDidDisappear(); + currentViewController.viewDidAppear(view); + + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + + public boolean isBackAvailable() { + return !currentViewController.equals(rootViewController); + } + + public ViewController navigateBack() throws UnsupportedOperationException { + if (currentViewController.equals(rootViewController)) { + throw new UnsupportedOperationException("No way back from the root view controller"); + } + + if (!currentViewController.checkBeforeExit()) { + return null; + } + + try { + ViewController redundantViewController = currentViewController; + redundantViewController.viewWillDisappear(); + + currentViewController = viewControllerStack.pop(); + + Parent view = currentViewController.obtainView(); + currentViewController.viewWillAppear(view); + delegate.onViewControllerActivated(currentViewController, view); + redundantViewController.viewDidDisappear(); + currentViewController.viewDidAppear(view); + } catch (IOException e) { + e.printStackTrace(); + } + + return currentViewController; + } +} diff --git a/testar/src/nl/ou/testar/jfx/core/NavigationDelegate.java b/testar/src/nl/ou/testar/jfx/core/NavigationDelegate.java new file mode 100644 index 000000000..3b1f39bbd --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/core/NavigationDelegate.java @@ -0,0 +1,7 @@ +package nl.ou.testar.jfx.core; + +import javafx.scene.Parent; + +public interface NavigationDelegate { + void onViewControllerActivated(ViewController viewController, Parent view); +} diff --git a/testar/src/nl/ou/testar/jfx/core/ViewController.java b/testar/src/nl/ou/testar/jfx/core/ViewController.java new file mode 100644 index 000000000..1b4407f80 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/core/ViewController.java @@ -0,0 +1,71 @@ +package nl.ou.testar.jfx.core; + +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import org.testar.monkey.Settings; + +import java.io.IOException; +import java.lang.ref.WeakReference; + +public abstract class ViewController { + + private WeakReference viewReference = new WeakReference<>(null); + private String title; + private String resourcePath; + protected Settings settings; + + private NavigationController navigationController; + + public String getTitle() { + return title; + } + + public NavigationController getNavigationController() { + return navigationController; + } + + public void setNavigationController(NavigationController navigationController) { + this.navigationController = navigationController; + } + + public ViewController(String title, String resourcePath, Settings settings) { + this.title = title; + this.resourcePath = resourcePath; + this.settings = settings; + } + + public Parent obtainView() throws IOException { + Parent view = viewReference.get(); + if (view == null) { + FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource(resourcePath)); + view = loader.load(); + viewDidLoad(view); + } + viewReference = new WeakReference<>(view); + return view; + } + + public void viewDidLoad(Parent view) { + // To be overridden + } + + public void viewWillAppear(Parent view) { + // To be overridden + } + + public void viewDidAppear(Parent view) { + // To be overridden + } + + public void viewWillDisappear() { + // To be overridden + } + + public void viewDidDisappear() { + // to be overridden + } + + public boolean checkBeforeExit() { + return true; + } +} diff --git a/testar/src/nl/ou/testar/jfx/dashboard/DashboardController.java b/testar/src/nl/ou/testar/jfx/dashboard/DashboardController.java new file mode 100644 index 000000000..c62d00415 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/dashboard/DashboardController.java @@ -0,0 +1,150 @@ +package nl.ou.testar.jfx.dashboard; + +import javafx.application.Platform; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import nl.ou.testar.jfx.core.ViewController; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.RuntimeControlsProtocol; +import org.testar.monkey.Settings; +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; +import javafx.stage.Stage; +import nl.ou.testar.jfx.WhiteboxTestStatus; +import nl.ou.testar.jfx.thirdparty.DisplayShelf; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +public class DashboardController extends ViewController { + + private String settingsPath; + + private DashboardDelegate delegate; + + public DashboardController(Settings settings, String settingsPath) { + super("Dashboard", "jfx/dashboard.fxml", settings); + this.settingsPath = settingsPath; + } + + public DashboardDelegate getDelegate() { + return delegate; + } + + public void setDelegate(DashboardDelegate delegate) { + this.delegate = delegate; + } + + private void startTesting(Parent view, RuntimeControlsProtocol.Modes mode) { + try { + checkSettings(settings); + settings.set(ConfigTags.Mode, mode); + System.out.println("Start testing..."); + if (delegate != null) { + Platform.runLater(() -> new Thread(() -> delegate.startTesting(settings)).start()); + + final Stage stage = (Stage) view.getScene().getWindow(); + } + else { + System.out.println("No delegate!"); + } + } catch (IllegalStateException ise) { + final Alert alert = new Alert(Alert.AlertType.ERROR, ise.getMessage()); + alert.show(); + } + } + + private void startWhiteboxTesting(Parent view) { + final Stage stage = (Stage) view.getScene().getWindow(); + final WhiteboxTestStatus testStatus = new WhiteboxTestStatus(); + + try { + testStatus.start(stage, settings); + } + catch(Exception e) { + testStatus.stop(); + final Alert alert = new Alert(Alert.AlertType.ERROR, "Cannot analyse code\n" + e.getMessage()); + alert.show(); + + e.printStackTrace(); + } + } + + private void checkSettings(Settings settings) throws IllegalStateException { + String userInputPattern = settings.get(ConfigTags.ProcessesToKillDuringTest); + try { + Pattern.compile(userInputPattern); + } catch (PatternSyntaxException exception) { + throw new IllegalStateException("Your ProcessFilter is not a valid regular expression!"); + } + + userInputPattern = settings.get(ConfigTags.ClickFilter); + try { + Pattern.compile(userInputPattern); + } catch (PatternSyntaxException exception) { + throw new IllegalStateException("Your ClickFilter is not a valid regular expression!"); + } + + userInputPattern = settings.get(ConfigTags.SuspiciousTitles); + try { + Pattern.compile(userInputPattern); + } catch (PatternSyntaxException exception) { + throw new IllegalStateException("Your Oracle is not a valid regular expression!"); + } + + if (!new File(settings.get(ConfigTags.OutputDir)).exists()) { + throw new IllegalStateException("Output Directory does not exist!"); + } + if (!new File(settings.get(ConfigTags.TempDir)).exists()) { + throw new IllegalStateException("Temp Directory does not exist!"); + } +// +// settingPanels.forEach((k,v) -> v.right().checkSettings()); + } + + + @Override + public void viewDidLoad(Parent view) { + Button btnSpyMode = (Button) view.lookup("#btnSpyMode"); + btnSpyMode.setOnAction(event -> { + startTesting(view, RuntimeControlsProtocol.Modes.Spy); + }); + + Button btnAutoTest = (Button) view.lookup("#btnAutoTest"); + btnAutoTest.setOnAction(event -> { + startTesting(view, RuntimeControlsProtocol.Modes.Generate); + }); + + Button btnRecTest = (Button) view.lookup("#btnRecTest"); + btnRecTest.setOnAction(event -> { + startTesting(view, RuntimeControlsProtocol.Modes.Record); + }); + + Button btnReplayTest = (Button) view.lookup("#btnReplayTest"); + btnReplayTest.setOnAction(event -> { + startTesting(view, RuntimeControlsProtocol.Modes.Replay); + }); + + Button btnWhiteboxTest = (Button) view.lookup("#btnWhiteboxTest"); + btnWhiteboxTest.setOnAction(event -> { + startWhiteboxTesting(view); + }); + + Button btnViewReports = (Button) view.lookup("#btnViewReports"); + btnViewReports.setOnAction(event -> { + startTesting(view, RuntimeControlsProtocol.Modes.View); + }); + + HBox carouselBox = (HBox) view.lookup("#carouselBox"); + final String imagePaths[] = {"/logos/ing.png", "/logos/marviq.png", "/logos/open_university.png", "/logos/philips.png", "/logos/sogeti.png"}; + final Image images[] = Arrays.stream(imagePaths).map(path -> new Image(path)).toArray(Image[]::new); + DisplayShelf carouselView = new DisplayShelf(images); + carouselBox.getChildren().add(carouselView); + carouselView.prefWidthProperty().bind(carouselBox.widthProperty()); + carouselView.prefHeightProperty().bind(carouselBox.heightProperty()); + } +} diff --git a/testar/src/nl/ou/testar/jfx/dashboard/DashboardDelegate.java b/testar/src/nl/ou/testar/jfx/dashboard/DashboardDelegate.java new file mode 100644 index 000000000..98feafbd1 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/dashboard/DashboardDelegate.java @@ -0,0 +1,7 @@ +package nl.ou.testar.jfx.dashboard; + +import org.testar.monkey.Settings; + +public interface DashboardDelegate { + void startTesting(Settings settings); +} diff --git a/testar/src/nl/ou/testar/jfx/misc/MiscController.java b/testar/src/nl/ou/testar/jfx/misc/MiscController.java new file mode 100644 index 000000000..ea703b9a7 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/misc/MiscController.java @@ -0,0 +1,10 @@ +package nl.ou.testar.jfx.misc; + +import nl.ou.testar.jfx.core.ViewController; +import org.testar.monkey.Settings; + +public class MiscController extends ViewController { + public MiscController(String title, Settings settings) { + super(title, "jfx/misc.fxml", settings); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/SettingsController.java b/testar/src/nl/ou/testar/jfx/settings/SettingsController.java new file mode 100644 index 000000000..e90c7a14d --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/SettingsController.java @@ -0,0 +1,49 @@ +package nl.ou.testar.jfx.settings; + +import javafx.scene.Parent; +import javafx.scene.control.Button; +import nl.ou.testar.jfx.core.ViewController; +import nl.ou.testar.jfx.settings.child.*; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Settings; + +public class SettingsController extends ViewController { + + private String settingsPath; + + public SettingsController(Settings settings, String settingsPath) { + super("Settings", "jfx/settings_new.fxml", settings); + this.settingsPath = settingsPath; + } + + @Override + public void viewDidLoad(Parent view) { + Button btnGeneral = (Button) view.lookup("#btnGeneral"); + Button btnFilters = (Button) view.lookup("#btnFilters"); + Button btnTime = (Button) view.lookup("#btnTime"); + Button btnMisc = (Button) view.lookup("#btnMisc"); + Button btnWhitebox = (Button) view.lookup("#btnWhitebox"); + Button btnState = (Button) view.lookup("#btnState"); + + btnGeneral.setOnAction(event -> { + getNavigationController().navigateTo(new GeneralSettingsController(settings, settingsPath), true); + }); + btnFilters.setOnAction(event -> { + getNavigationController().navigateTo(new FilterSettingsController(settings, settingsPath), true); + }); + btnTime.setOnAction(event -> { + getNavigationController().navigateTo(new TimeSettingsController(settings, settingsPath), true); + }); + btnMisc.setOnAction(event -> { + getNavigationController().navigateTo(new MiscSettingsController(settings, settingsPath), true); + }); + btnWhitebox.setOnAction(event -> { + getNavigationController().navigateTo(new WhiteboxSettingsController(settings, settingsPath), true); + }); + btnState.setOnAction(event -> { + getNavigationController().navigateTo(new StateSettingsController(settings, settingsPath), true); + }); + + btnState.setDisable(!settings.get(ConfigTags.StateModelEnabled, false)); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/AbstractConfigBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/AbstractConfigBinding.java new file mode 100644 index 000000000..8bc441df5 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/AbstractConfigBinding.java @@ -0,0 +1,31 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.Control; + +public abstract class AbstractConfigBinding { + + protected C control; + protected T value; + + public AbstractConfigBinding(C control) { + this.control = control; + } + + public C getControl() { + return control; + } + + protected abstract T getTargetValue(); + protected abstract void setTargetValue(T value); + + public void save() { + setTargetValue(value); + }; + + public boolean needsSave() { + T targetValue = getTargetValue(); + return !((value == null && targetValue == null) || value.equals(targetValue)); + } + + public abstract void onBind(); +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/CheckTagBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/CheckTagBinding.java new file mode 100644 index 000000000..57ef21e3b --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/CheckTagBinding.java @@ -0,0 +1,19 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.CheckBox; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class CheckTagBinding extends ConfigTagBinding { + public CheckTagBinding(Settings settings, CheckBox control, Tag tag) { + super(settings, control, tag); + } + + @Override + public void onBind() { + control.setSelected(value); + control.selectedProperty().addListener((observable, oldValue, newValue) -> { + value = newValue; + }); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/ComboBoxTagBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/ComboBoxTagBinding.java new file mode 100644 index 000000000..565569799 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/ComboBoxTagBinding.java @@ -0,0 +1,19 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.ComboBox; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class ComboBoxTagBinding extends ConfigTagBinding, T> { + public ComboBoxTagBinding(Settings settings, ComboBox control, Tag tag) { + super(settings, control, tag); + } + + @Override + public void onBind() { + control.setValue(value); + control.valueProperty().addListener((observable, oldValue, newValue) -> { + value = newValue; + }); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigBinding.java new file mode 100644 index 000000000..b0cd47d56 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigBinding.java @@ -0,0 +1,198 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.*; +import nl.ou.testar.jfx.settings.bindings.control.*; +import nl.ou.testar.jfx.settings.bindings.data.DataSource; +import nl.ou.testar.jfx.settings.bindings.data.TagDataSource; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class ConfigBinding { + + public enum GenericType { + FIELD_STRING, FIELD_INT, FIELD_DOUBLE, TEXT_INPUT, CHECK_BOX, COMBO_BOX + } + + private ControlBinding controlBinding; + private DataSource dataSource; + + private T value; + + private ConfigBinding(ControlBinding controlBinding, DataSource dataSource) { + this.controlBinding = controlBinding; + this.dataSource = dataSource; + this.value = dataSource.getData(); + } + + public void bind() { + controlBinding. setValue(value); + controlBinding.onBind(value -> { + setValue(value); + }); + } + + public void setValue(T value) { + this.value = value; + controlBinding.setValue(value); + } + + public T getValue() { + return value; + } + + public T resetValue() { + setValue(dataSource.getData());; + return value; + } + + public boolean needsSave() { + T data = dataSource.getData(); + if (value == null) { + return dataSource.getData() != null; + } + return !value.equals(data); + } + + public void save() { + dataSource.setData(value); + } + + + public static class Builder { + private Control control; + private GenericType genericType; + private Settings settings; + private Tag tag; + + private ControlBinding customControlBinding; + private DataSource customDataSource; + + public Builder withControl(Control control) { + this.control = control; + return this; + } + + public Builder withGenericType(GenericType genericType) { + this.genericType = genericType; + return this; + } + + public Builder withSettings(Settings settings) { + this.settings = settings; + return this; + } + + public Builder withTag(Tag tag) { + this.tag = tag; + return this; + } + + public Builder withCustomControlBinding(ControlBinding customControlBinding) { + this.customControlBinding = customControlBinding; + return this; + } + + public Builder withCustomDataSource(DataSource dataSource) { + this.customDataSource = dataSource; + return this; + } + + public ConfigBinding build() throws ConfigBindingException { + + ControlBinding controlBinding = customControlBinding; + DataSource dataSource = customDataSource; + + if (dataSource == null) { + if (settings == null) { + throw new ConfigBindingException("Either settings object or custom data source should be set"); + } + if (tag == null) { + throw new ConfigBindingException("Either settings tag or custom data source should be set"); + } + + TagDataSource tagDataSource = new TagDataSource(settings, tag); + if (genericType == GenericType.FIELD_STRING || genericType == GenericType.TEXT_INPUT) { + tagDataSource.setDefaultValue(""); + } + else if (genericType == GenericType.FIELD_INT) { + tagDataSource.setDefaultValue(new Integer(0)); + } + else if (genericType == GenericType.FIELD_DOUBLE) { + tagDataSource.setDefaultValue(new Double(0)); + } + else if (genericType == GenericType.CHECK_BOX) { + tagDataSource.setDefaultValue(new Boolean(false)); + } + dataSource = tagDataSource; + } + + if (controlBinding == null) { + if (control == null) { + throw new ConfigBindingException("Control not set"); + } + if (genericType == null) { + throw new ConfigBindingException("Either generic type or custom control binding should be set"); + } + switch (genericType) { + case TEXT_INPUT: + assertControlTypeMatch(control, TextArea.class); + assertDataTypeMatch(dataSource, String.class); + controlBinding = new TextAreaBinding((TextArea) control); + break; + case FIELD_STRING: + assertControlTypeMatch(control, TextField.class); + assertDataTypeMatch(dataSource, String.class); + controlBinding = new StringFieldBinding((TextField) control); + break; + case FIELD_INT: + assertControlTypeMatch(control, TextField.class); + assertDataTypeMatch(dataSource, Integer.class); + controlBinding = new IntegerFieldBinding((TextField) control); + break; + case FIELD_DOUBLE: + assertControlTypeMatch(control, TextField.class); + assertDataTypeMatch(dataSource, Double.class); + controlBinding = new DoubleFieldBinding((TextField) control); + break; + case CHECK_BOX: + assertControlTypeMatch(control, CheckBox.class); + assertDataTypeMatch(dataSource, Boolean.class); + controlBinding = new CheckBoxBinding((CheckBox) control); + break; + case COMBO_BOX: + assertControlTypeMatch(control, ComboBox.class); + controlBinding = new ComboBoxBinding((ComboBox) control); + break; + default: + throw new ConfigBindingException(String.format("Unknown generic type: %s", genericType.toString())); + } + } + + ConfigBinding configBinding = new ConfigBinding(controlBinding, dataSource); + + // Reset builder to reuse it + control = null; + genericType = null; + settings = null; + tag = null; + customControlBinding = null; + customDataSource = null; + + return configBinding; + } + private void assertControlTypeMatch(Control control, Class expectedControlType) + throws ConfigBindingException { + if (!expectedControlType.isInstance(control)) { + throw new ConfigBindingException(String.format("Control type mismatch: expected %s, actual %s", + expectedControlType.getSimpleName(), control.getClass().getSimpleName())); + } + }; + private void assertDataTypeMatch(DataSource dataSource, Class expectedTagType) + throws ConfigBindingException { + if (!dataSource.getDataType().isAssignableFrom(expectedTagType)) { + throw new ConfigBindingException(String.format("Data type mismatch: expected %s, actual %s", + expectedTagType.getSimpleName(), dataSource.getDataType().getSimpleName())); + } + }; + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigBindingException.java b/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigBindingException.java new file mode 100644 index 000000000..bc57cd5e1 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigBindingException.java @@ -0,0 +1,7 @@ +package nl.ou.testar.jfx.settings.bindings; + +public class ConfigBindingException extends Exception { + public ConfigBindingException(String errorMessage) { + super(errorMessage); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigTagBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigTagBinding.java new file mode 100644 index 000000000..b3ffe177a --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/ConfigTagBinding.java @@ -0,0 +1,62 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.*; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public abstract class ConfigTagBinding extends AbstractConfigBinding { + + public enum Type { + FIELD_STRING, FIELD_INT, FIELD_DOUBLE, TEXT_INPUT, CHECK_BOX, COMBO_BOX + } + + protected Settings settings; + protected Tag tag; + + public ConfigTagBinding(Settings settings, C control, Tag tag) { + super(control); + this.settings = settings; + this.tag = tag; + this.value = settings.get(tag); + } + + public Tag getTag() { + return tag; + } + + @Override + protected T getTargetValue() { + return settings.get(tag); + } + + @Override + protected void setTargetValue(T value) { + settings.set(tag, value); + } + + public static ConfigTagBinding bind(Settings settings, Control control, Tag tag, Type type) { + ConfigTagBinding binding; + switch (type) { + case FIELD_STRING: + binding = new StringFieldTagBinding(settings, (TextField) control, tag); + break; + case FIELD_INT: + binding = new IntegerFieldTagBinding(settings, (TextField) control, tag); + break; + case FIELD_DOUBLE: + binding = new DoubleInputBinding(settings, (TextField) control, tag); + break; + case TEXT_INPUT: + binding = new TextInputBinding(settings, (TextInputControl) control, tag); + break; + case CHECK_BOX: + binding = new CheckTagBinding(settings, (CheckBox) control, tag); + break; + default: // COMBO_BOX + binding = new ComboBoxTagBinding(settings, (ComboBox) control, tag); + break; + } + binding.onBind(); + return binding; + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/DoubleInputBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/DoubleInputBinding.java new file mode 100644 index 000000000..b786973d1 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/DoubleInputBinding.java @@ -0,0 +1,29 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.TextField; +import org.apache.commons.lang.math.NumberUtils; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class DoubleInputBinding extends FieldTagBinding { + public DoubleInputBinding(Settings settings, TextField control, Tag tag) { + super(settings, control, tag); + } + + @Override + protected String getInputPattern() { + // Here we consider only non-negative fixed-point decimal numbers + return "\\d*|\\d+\\,\\d*"; + } + + @Override + protected Double valueFromText(String text) { + return NumberUtils.toDouble(text, 0); + } + + @Override + public void onBind() { + super.onBind(); + control.setPromptText("0"); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/FieldTagBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/FieldTagBinding.java new file mode 100644 index 000000000..c1974590b --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/FieldTagBinding.java @@ -0,0 +1,43 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.TextField; +import javafx.scene.control.TextFormatter; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +import java.util.function.UnaryOperator; +import java.util.regex.Pattern; + +public abstract class FieldTagBinding extends ConfigTagBinding { + + protected String getInputPattern() { + return null; + } + + abstract protected T valueFromText(String text); + + protected String valueToText(T value) { + return value.toString(); + } + + public FieldTagBinding(Settings settings, TextField control, Tag tag) { + super(settings, control, tag); + } + + @Override + public void onBind() { + control.textProperty().set(valueToText(value)); + control.textProperty().addListener((observable, oldTextValue, newTextValue) -> { + value = valueFromText(newTextValue); + }); + + String patternString = getInputPattern(); + if (patternString != null) { + Pattern pattern = Pattern.compile(patternString); + TextFormatter formatter = new TextFormatter((UnaryOperator) change -> + pattern.matcher(change.getControlNewText()).matches() ? change : null); + + control.setTextFormatter(formatter); + } + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/IntegerFieldTagBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/IntegerFieldTagBinding.java new file mode 100644 index 000000000..e87889511 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/IntegerFieldTagBinding.java @@ -0,0 +1,30 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.TextField; +import org.apache.commons.lang.math.NumberUtils; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class IntegerFieldTagBinding extends FieldTagBinding { + + public IntegerFieldTagBinding(Settings settings, TextField control, Tag tag) { + super(settings, control, tag); + } + + @Override + protected String getInputPattern() { + // Here we consider only non-negative decimal numbers + return "\\d*"; + } + + @Override + protected Integer valueFromText(String text) { + return NumberUtils.toInt(text, 0); + } + + @Override + public void onBind() { + super.onBind(); + control.setPromptText("0"); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/StringFieldTagBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/StringFieldTagBinding.java new file mode 100644 index 000000000..acf600421 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/StringFieldTagBinding.java @@ -0,0 +1,17 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.TextField; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class StringFieldTagBinding extends FieldTagBinding { + + public StringFieldTagBinding(Settings settings, TextField control, Tag tag) { + super(settings, control, tag); + } + + @Override + protected String valueFromText(String text) { + return text; + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/TextInputBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/TextInputBinding.java new file mode 100644 index 000000000..4739eb3e4 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/TextInputBinding.java @@ -0,0 +1,20 @@ +package nl.ou.testar.jfx.settings.bindings; + +import javafx.scene.control.TextInputControl; +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class TextInputBinding extends ConfigTagBinding { + + public TextInputBinding(Settings settings, TextInputControl control, Tag tag) { + super(settings, control, tag); + } + + @Override + public void onBind() { + control.setText(value); + control.textProperty().addListener((observable, oldValue, newValue) -> { + value = newValue; + }); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/AbstractControlBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/AbstractControlBinding.java new file mode 100644 index 000000000..5aaff5e32 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/AbstractControlBinding.java @@ -0,0 +1,12 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.Control; + +public abstract class AbstractControlBinding implements ControlBinding { + + protected C control; + + public AbstractControlBinding(C control) { + this.control = control; + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/CheckBoxBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/CheckBoxBinding.java new file mode 100644 index 000000000..1bdbdb4bd --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/CheckBoxBinding.java @@ -0,0 +1,25 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.CheckBox; + +public class CheckBoxBinding extends AbstractControlBinding { + + public CheckBoxBinding(CheckBox control) { + super(control); + } + + @Override + public void setValue(Boolean value) { + control.setSelected(value); + } + + @Override + public Boolean getValue() { + return control.isSelected(); + } + + @Override + public void onBind(Callback callback) { + control.selectedProperty().addListener((observable, oldValue, newValue) -> callback.onUpdate(newValue)); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/ComboBoxBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/ComboBoxBinding.java new file mode 100644 index 000000000..7e356dcb3 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/ComboBoxBinding.java @@ -0,0 +1,33 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.ComboBox; + +public class ComboBoxBinding extends AbstractControlBinding, T> { + + public ComboBoxBinding(ComboBox control) { + super(control); + } + + @Override + public void setValue(T value) { + int index = 0; + for (T currentValue: control.getItems()) { + if (currentValue.equals(value)) { + control.getSelectionModel().select(index); + } + index++; + } + } + + @Override + public T getValue() { + return control.getValue(); + } + + @Override + public void onBind(Callback callback) { + control.valueProperty().addListener((observable, oldValue, newValue) -> { + callback.onUpdate(newValue); + }); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/ControlBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/ControlBinding.java new file mode 100644 index 000000000..278a3c07d --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/ControlBinding.java @@ -0,0 +1,12 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +public interface ControlBinding { + + interface Callback { + void onUpdate(S value); + } + + void setValue(T value); + T getValue(); + void onBind(Callback callback); +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/DoubleFieldBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/DoubleFieldBinding.java new file mode 100644 index 000000000..347d29709 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/DoubleFieldBinding.java @@ -0,0 +1,22 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.TextField; +import org.apache.commons.lang.math.NumberUtils; + +public class DoubleFieldBinding extends FieldBinding { + + public DoubleFieldBinding(TextField control) { + super(control); + } + + @Override + protected Double valueFromText(String text) { + return NumberUtils.toDouble(text, 0); + } + + @Override + public void onBind(Callback callback) { + super.onBind(callback); + control.setPromptText("0"); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/FieldBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/FieldBinding.java new file mode 100644 index 000000000..6bb314634 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/FieldBinding.java @@ -0,0 +1,49 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.TextField; +import javafx.scene.control.TextFormatter; + +import java.util.function.UnaryOperator; +import java.util.regex.Pattern; + +public abstract class FieldBinding extends AbstractControlBinding { + + public FieldBinding(TextField control) { + super(control); + } + + protected String getInputPattern() { + return null; + } + + abstract protected T valueFromText(String text); + + protected String valueToText(T value) { + return value == null ? "" : value.toString(); + } + + @Override + public void setValue(T value) { + control.setText(valueToText(value)); + } + + @Override + public T getValue() { + return valueFromText(control.getText()); + } + + @Override + public void onBind(Callback callback) { + control.textProperty().addListener((observable, oldValue, newValue) -> + callback.onUpdate(valueFromText(newValue))); + + String patternString = getInputPattern(); + if (patternString != null) { + Pattern pattern = Pattern.compile(patternString); + TextFormatter formatter = new TextFormatter((UnaryOperator) change -> + pattern.matcher(change.getControlNewText()).matches() ? change : null); + + control.setTextFormatter(formatter); + } + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/IntegerFieldBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/IntegerFieldBinding.java new file mode 100644 index 000000000..8891d7dbd --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/IntegerFieldBinding.java @@ -0,0 +1,22 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.TextField; +import org.apache.commons.lang.math.NumberUtils; + +public class IntegerFieldBinding extends FieldBinding { + + public IntegerFieldBinding(TextField control) { + super(control); + } + + @Override + protected Integer valueFromText(String text) { + return NumberUtils.toInt(text, 0); + } + + @Override + public void onBind(Callback callback) { + super.onBind(callback); + control.setPromptText("0"); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/StringFieldBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/StringFieldBinding.java new file mode 100644 index 000000000..40dbbee0f --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/StringFieldBinding.java @@ -0,0 +1,15 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.TextField; + +public class StringFieldBinding extends FieldBinding { + + public StringFieldBinding(TextField control) { + super(control); + } + + @Override + protected String valueFromText(String text) { + return text; + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/control/TextAreaBinding.java b/testar/src/nl/ou/testar/jfx/settings/bindings/control/TextAreaBinding.java new file mode 100644 index 000000000..79ed385ee --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/control/TextAreaBinding.java @@ -0,0 +1,28 @@ +package nl.ou.testar.jfx.settings.bindings.control; + +import javafx.scene.control.TextArea; +import nl.ou.testar.jfx.settings.bindings.AbstractConfigBinding; + +public class TextAreaBinding extends AbstractControlBinding { + + public TextAreaBinding(TextArea control) { + super(control); + } + + @Override + public void setValue(String value) { + control.setText(value); + } + + @Override + public String getValue() { + return control.getText(); + } + + @Override + public void onBind(Callback callback) { + control.textProperty().addListener((observable, oldValue, newValue) -> { + callback.onUpdate(newValue); + }); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/data/DataSource.java b/testar/src/nl/ou/testar/jfx/settings/bindings/data/DataSource.java new file mode 100644 index 000000000..1a2b45d0c --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/data/DataSource.java @@ -0,0 +1,7 @@ +package nl.ou.testar.jfx.settings.bindings.data; + +public interface DataSource { + Class getDataType(); + T getData(); + void setData(T data); +} diff --git a/testar/src/nl/ou/testar/jfx/settings/bindings/data/TagDataSource.java b/testar/src/nl/ou/testar/jfx/settings/bindings/data/TagDataSource.java new file mode 100644 index 000000000..0d8951e02 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/bindings/data/TagDataSource.java @@ -0,0 +1,39 @@ +package nl.ou.testar.jfx.settings.bindings.data; + +import org.testar.monkey.Settings; +import org.testar.monkey.alayer.Tag; + +public class TagDataSource implements DataSource { + + private Settings settings; + private Tag tag; + private T defaultValue = null; + + public TagDataSource(Settings settings, Tag tag) { + this.settings = settings; + this.tag = tag; + } + + public void setDefaultValue(T defaultValue) { + this.defaultValue = defaultValue; + } + + public T getDefaultValue() { + return defaultValue; + } + + @Override + public Class getDataType() { + return tag.type(); + } + + @Override + public T getData() { + return settings.get(tag, defaultValue); + } + + @Override + public void setData(T data) { + settings.set(tag, data); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/child/FilterSettingsController.java b/testar/src/nl/ou/testar/jfx/settings/child/FilterSettingsController.java new file mode 100644 index 000000000..459baf8d3 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/child/FilterSettingsController.java @@ -0,0 +1,236 @@ +package nl.ou.testar.jfx.settings.child; + +import com.jfoenix.controls.JFXTextArea; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import nl.ou.testar.jfx.controls.TagControl; +import nl.ou.testar.jfx.controls.TagInput; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Settings; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class FilterSettingsController extends SettingsEditController { + + private final static String descriptions[] = { + "Filter actions on the widgets based on Tags values (regular expression):", + "Tags to apply the filters (semicolon to customize multiple Tags)", + "Kill processes by name (regular expression):", + "Suspicious Titles based on Tags values (regular expression)", + "Tags to apply the Suspicious Titles (semicolon to customize multiple Tags)", + "Suspicious Process Output (regular expression)" + }; + + private int selectedIndex = 0; + + private Label descriptionLabel; + private JFXTextArea textArea; + private FlowPane tagsPane; + private Button choiceButtons[] = new Button[6]; + + private String clickFilter; + private String processesToKill; + private String suspiciousTitles; + private String suspiciousProcessOutput; + + private List filterTags; + private List oracleTags; + + FXMLLoader tagLoader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/tag.fxml")); + + private void selectItem(int index) { + if (index == selectedIndex) { + return; + } + + storeValue(selectedIndex); + + setSelection(selectedIndex, false); + setSelection(index, true); + selectedIndex = index; + } + + private void storeValue(int index) { + switch(index) { + case 0: + clickFilter = textArea.getText(); + break; + case 1: + filterTags = readTagsFromPane(tagsPane); + break; + case 2: + processesToKill = textArea.getText(); + break; + case 3: + suspiciousTitles = textArea.getText(); + break; + case 4: + oracleTags = readTagsFromPane(tagsPane); + break; + default: + suspiciousProcessOutput = textArea.getText(); + break; + } + } + + private void setSelection(int index, boolean selected) { + if (selected) { + descriptionLabel.setText(descriptions[index]); + choiceButtons[index].setStyle("-fx-background-color:#a7a7a7;-fx-background-radius:18"); + } + else { + choiceButtons[index].setStyle("-fx-background-color:#f7f7f7;;-fx-background-radius:18"); + } + + switch (index) { + case 0: + textArea.setVisible(true); + tagsPane.setVisible(false); + textArea.setText(clickFilter); + break; + case 1: + textArea.setVisible(false); + tagsPane.setVisible(true); + fillPaneWithTags(tagsPane, filterTags); + break; + case 2: + textArea.setVisible(true); + tagsPane.setVisible(false); + textArea.setText(processesToKill); + break; + case 3: + textArea.setVisible(true); + tagsPane.setVisible(false); + textArea.setText(suspiciousTitles); + break; + case 4: + textArea.setVisible(false); + tagsPane.setVisible(true); + fillPaneWithTags(tagsPane, oracleTags); + break; + default: + textArea.setVisible(true); + tagsPane.setVisible(false); + textArea.setText(suspiciousProcessOutput); + break; + } + } + + public FilterSettingsController(Settings settings, String settingsPath) { + super("Filters & oracles", settings, settingsPath); + } + + @Override + public void viewDidLoad(Parent view) { + super.viewDidLoad(view); + Parent filterSection = null; + try { + filterSection = putSection(view, "Filters & oracles", "jfx/settings_filter.fxml"); + } catch (IOException e) { + e.printStackTrace(); + } + + clickFilter = settings.get(ConfigTags.ClickFilter, ""); + filterTags = settings.get(ConfigTags.TagsToFilter, Collections.emptyList()); + processesToKill = settings.get(ConfigTags.ProcessesToKillDuringTest, ""); + suspiciousTitles = settings.get(ConfigTags.SuspiciousTitles, ""); + oracleTags = settings.get(ConfigTags.TagsForSuspiciousOracle, Collections.emptyList()); + suspiciousProcessOutput = settings.get(ConfigTags.SuspiciousProcessOutput, ""); + + descriptionLabel = (Label) filterSection.lookup("#descriptionLabel"); + textArea = (JFXTextArea) filterSection.lookup("#textArea"); + tagsPane = (FlowPane) filterSection.lookup("#tagsPane"); + + choiceButtons[0] = (Button) filterSection.lookup("#btnFilterClick"); + choiceButtons[0].setOnAction(event -> { + selectItem(0); + }); + choiceButtons[1] = (Button) filterSection.lookup("#btnFilterTags"); + choiceButtons[1].setOnAction(event -> {selectItem(1);}); + choiceButtons[2] = (Button) filterSection.lookup("#btnFilterProcess"); + choiceButtons[2].setOnAction(event -> {selectItem(2);}); + choiceButtons[3] = (Button) filterSection.lookup("#btnOracleTitles"); + choiceButtons[3].setOnAction(event -> {selectItem(3);}); + choiceButtons[4] = (Button) filterSection.lookup("#btnOracleTags"); + choiceButtons[4].setOnAction(event -> {selectItem(4);}); + choiceButtons[5] = (Button) filterSection.lookup("#btnOracleProcess"); + choiceButtons[5].setOnAction(event -> {selectItem(5);}); + + setSelection(selectedIndex, true); + } + + private void fillPaneWithTags(FlowPane pane, List tags) { + pane.getChildren().clear(); + System.out.println(String.format("Found %d tag(s)", tags.size())); + pane.getChildren().addAll(tags.stream().map(tag -> { + final TagControl tagControl = new TagControl(tag); + tagControl.setDelegate(() -> { + pane.getChildren().remove(tagControl); + }); + return tagControl; + }/*new TagControl(tag, new TagControl.Delegate() { + @Override + public void onClose() { + pane.getChildren().remove(this); + } + }*/).collect(Collectors.toList())); + + final TagInput tagInput = new TagInput(); + tagInput.setDelegate(tag -> { + int index = pane.getChildren().size() - 1; + final TagControl tagControl = new TagControl(tag); + tagControl.setDelegate(() -> { + pane.getChildren().remove(tagControl); + }); + pane.getChildren().add(index, tagControl); + tagInput.clear(); + }); + pane.getChildren().add(tagInput); + } + + private List readTagsFromPane(FlowPane pane) { + return pane.getChildren().stream().filter(child -> TagControl.class.isInstance(child)) + .map(child -> ((TagControl) child).getTag()).collect(Collectors.toList()); + } + + @Override + protected boolean needsSave(Settings settings) { + if (clickFilter != null && !clickFilter.equals(settings.get(ConfigTags.ClickFilter, ""))) { + return true; + } + if (filterTags != null & !filterTags.equals(settings.get(ConfigTags.TagsToFilter, Collections.emptyList()))) { + return true; + } + if (processesToKill != null && !processesToKill.equals(settings.get(ConfigTags.ProcessesToKillDuringTest, ""))) { + return true; + } + if (suspiciousTitles != null && !suspiciousTitles.equals(settings.get(ConfigTags.SuspiciousTitles, ""))) { + return true; + } + if (oracleTags != null && !oracleTags.equals((settings.get(ConfigTags.TagsForSuspiciousOracle, Collections.emptyList())))) { + return true; + } + if (suspiciousProcessOutput != null && !suspiciousProcessOutput.equals(settings.get(ConfigTags.SuspiciousProcessOutput, ""))) { + return true; + } + return false; + } + + @Override + protected void save(Settings settings) { + storeValue(selectedIndex); + + settings.set(ConfigTags.ClickFilter, clickFilter); + settings.set(ConfigTags.TagsToFilter, filterTags); + settings.set(ConfigTags.ProcessesToKillDuringTest, processesToKill); + settings.set(ConfigTags.SuspiciousTitles, suspiciousTitles); + settings.set(ConfigTags.TagsForSuspiciousOracle, oracleTags); + settings.set(ConfigTags.SuspiciousProcessOutput, suspiciousProcessOutput); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/child/GeneralSettingsController.java b/testar/src/nl/ou/testar/jfx/settings/child/GeneralSettingsController.java new file mode 100644 index 000000000..e226a86b7 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/child/GeneralSettingsController.java @@ -0,0 +1,281 @@ +package nl.ou.testar.jfx.settings.child; + +import javafx.collections.FXCollections; +import javafx.scene.Parent; +import javafx.scene.control.*; +import javafx.stage.FileChooser; +import nl.ou.testar.jfx.settings.bindings.AbstractConfigBinding; +import nl.ou.testar.jfx.settings.bindings.ConfigBinding; +import nl.ou.testar.jfx.settings.bindings.ConfigBindingException; +import nl.ou.testar.jfx.settings.bindings.control.ComboBoxBinding; +import nl.ou.testar.jfx.settings.bindings.control.ControlBinding; +import nl.ou.testar.jfx.settings.bindings.control.StringFieldBinding; +import nl.ou.testar.jfx.settings.bindings.data.DataSource; +import nl.ou.testar.jfx.utils.DisplayModeWrapper; +import nl.ou.testar.jfx.utils.GeneralSettings; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Settings; + +import java.awt.DisplayMode; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class GeneralSettingsController extends SettingsEditController { + + private DisplayMode availableDisplayModes[]; + + private GeneralSettings generalSettings; + + public GeneralSettingsController(Settings settings, String settingsPath) { + super("General settings", settings, settingsPath); + } + + @Override + public void viewDidLoad(Parent view) { + super.viewDidLoad(view); + Parent generalSection = null; + try { + generalSection = putSection(view, "General settings", "jfx/settings_general.fxml"); + } catch (IOException e) { + e.printStackTrace(); + } + + System.out.println("General settings loaded"); + + GraphicsDevice dev = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice(); + availableDisplayModes = dev.getDisplayModes(); + +// TextField webDriverPathField = (TextField) generalSection.lookup("#driverPath"); +// TextField locationInputField = (TextField) generalSection.lookup("#locationInput"); +// +// Button btnSelectDriver = (Button) generalSection.lookup("#btnSelectDriver"); +// Button btnSelectLocation = (Button) generalSection.lookup("#btnSelectLocation"); +// +// TextField numSequencesField = (TextField) generalSection.lookup("#numSequences"); +// TextField numActionsField = (TextField) generalSection.lookup("#numActions"); +// CheckBox alwaysCompileCheckBox = (CheckBox) generalSection.lookup("#alwaysCompile"); + +// if (webDriverPathField == null) { +// System.out.println("Failed to lookup web driver path field"); +// } +// if (locationInputField == null) { +// System.out.println("Failed to lookup location input field"); +// } +// if (btnSelectDriver == null) { +// System.out.println("Failed to lookup driver selection button"); +// } +// if (btnSelectLocation == null) { +// System.out.println("Failed to lookup location selection button"); +// } +// if (numSequencesField == null) { +// System.out.println("Failed to lookup sequence number field"); +// } +// if (numActionsField == null) { +// System.out.println("Failed to lookup action number field"); +// } +// if (alwaysCompileCheckBox == null) { +// System.out.println("Failed to lookup sa check box"); +// } + + ComboBox sutComboBox = (ComboBox) generalSection.lookup("#sutConnectorSelection"); + if (sutComboBox == null) { + System.out.println("Failed to lookup SUT combo box"); + } + sutComboBox.getItems().addAll( + Settings.SUT_CONNECTOR_CMDLINE, + Settings.SUT_CONNECTOR_PROCESS_NAME, + Settings.SUT_CONNECTOR_WINDOW_TITLE, + Settings.SUT_CONNECTOR_WEBDRIVER + ); + + final List availableResolutions = Arrays.stream(availableDisplayModes).map(mode -> new DisplayModeWrapper(mode, true)) + .collect(Collectors.toList()); + ComboBox resolutionComboBox = (ComboBox) generalSection.lookup("#resolutionSelection"); + DisplayMode currentDisplayMode = dev.getDisplayMode(); + System.out.println("Current display mode: " + currentDisplayMode); + System.out.println(String.format("Current dislpay mode: %dx%d+%d+%d", currentDisplayMode.getWidth(), currentDisplayMode.getHeight(), currentDisplayMode.getBitDepth(), currentDisplayMode.getRefreshRate())); + generalSettings = new GeneralSettings(settings.get(ConfigTags.SUTConnectorValue, ""), currentDisplayMode); + + DisplayMode selectedDisplayMode = generalSettings.getDisplayMode(); + if (selectedDisplayMode == null) { + selectedDisplayMode = currentDisplayMode; + } + + if (!isModeAvailable(selectedDisplayMode)) { + availableResolutions.add(new DisplayModeWrapper(selectedDisplayMode, false)); + } + resolutionComboBox.setItems(FXCollections.observableArrayList(availableResolutions)); + + TextField webDriverPathField = (TextField) generalSection.lookup("#driverPath"); + TextField locationInputField = (TextField) generalSection.lookup("#locationInput"); + + FileChooser driverChooser = new FileChooser(); + FileChooser locationChooser = new FileChooser(); + + Button btnSelectDriver = (Button) generalSection.lookup("#btnSelectDriver"); + Button btnSelectLocation = (Button) generalSection.lookup("#btnSelectLocation"); + + TextField numSequencesField = (TextField) generalSection.lookup("#numSequences"); + TextField numActionsField = (TextField) generalSection.lookup("#numActions"); + CheckBox alwaysCompileCheckBox = (CheckBox) generalSection.lookup("#alwaysCompile"); + + AbstractConfigBinding webDriverBinding = new AbstractConfigBinding(webDriverPathField) { + @Override + protected String getTargetValue() { + return generalSettings.getDriver(); + } + + @Override + protected void setTargetValue(String value) { + generalSettings.setDriver(value); + } + + @Override + public void onBind() { + control.textProperty().set(getTargetValue()); + webDriverPathField.textProperty().addListener((observable, oldValue, newValue) -> { + setTargetValue(newValue); + }); + } + }; + + addBinding(numSequencesField, ConfigTags.Sequences, ConfigBinding.GenericType.FIELD_INT); + addBinding(numActionsField, ConfigTags.SequenceLength, ConfigBinding.GenericType.FIELD_INT); + addBinding(sutComboBox, ConfigTags.SUTConnector, ConfigBinding.GenericType.COMBO_BOX); + addBinding(alwaysCompileCheckBox, ConfigTags.AlwaysCompile, ConfigBinding.GenericType.CHECK_BOX); + + ConfigBinding.Builder builder = new ConfigBinding.Builder<>(); + + ControlBinding webDriverControlBinding = new StringFieldBinding(webDriverPathField); + DataSource webDriverDataSource = new DataSource() { + @Override + public Class getDataType() { + return String.class; + } + + @Override + public String getData() { + return generalSettings.getDriver(); + } + + @Override + public void setData(String data) { + generalSettings.setDriver(data); + } + }; + + try { + final ConfigBinding webDriverConfigBinding = builder + .withCustomControlBinding(webDriverControlBinding) + .withCustomDataSource(webDriverDataSource) + .build(); + + addBinding(webDriverConfigBinding); + + btnSelectDriver.setOnAction(event -> { + File driverFile = driverChooser.showOpenDialog(view.getScene().getWindow()); + webDriverConfigBinding.setValue(driverFile.getAbsolutePath()); + }); + } catch (ConfigBindingException e) { + e.printStackTrace(); + } + + ControlBinding locationControlBinding = new StringFieldBinding(locationInputField); + DataSource locationDataSource = new DataSource() { + @Override + public Class getDataType() { + return String.class; + } + + @Override + public String getData() { + return generalSettings.getLocation(); + } + + @Override + public void setData(String data) { + generalSettings.setLocation(data); + } + }; + + try { + final ConfigBinding locationConfigBinding = builder + .withCustomControlBinding(locationControlBinding) + .withCustomDataSource(locationDataSource) + .build(); + + addBinding(locationConfigBinding); + + btnSelectLocation.setOnAction(event -> { + File locationFile = locationChooser.showOpenDialog(view.getScene().getWindow()); + locationConfigBinding.setValue(locationFile.toURI().toString()); + }); + } catch (ConfigBindingException e) { + e.printStackTrace(); + } + + ControlBinding resolutionControlBinding = new ComboBoxBinding<>(resolutionComboBox); + DataSource resolutionDataSource = new DataSource() { + @Override + public Class getDataType() { + return DisplayModeWrapper.class; + } + + @Override + public DisplayModeWrapper getData() { + DisplayMode displayMode = generalSettings.getDisplayMode(); + if (displayMode == null) { + displayMode = currentDisplayMode; + } + return new DisplayModeWrapper(displayMode, isModeAvailable(displayMode)); + } + + @Override + public void setData(DisplayModeWrapper data) { + generalSettings.setDisplayMode(data.getMode()); + } + }; + try { + ConfigBinding resolutionConfigBinding = new ConfigBinding.Builder() + .withCustomControlBinding(resolutionControlBinding) + .withCustomDataSource(resolutionDataSource) + .build(); + addBinding(resolutionConfigBinding); + } catch (ConfigBindingException e) { + e.printStackTrace(); + } + } + + private boolean isModeAvailable(DisplayMode displayMode) { + if (availableDisplayModes == null) { + System.out.println("Available display modes set is null"); + } + if (displayMode == null) { + System.out.println("Display mode is null"); + } + return Arrays.stream(availableDisplayModes).anyMatch(displayMode::equals); + } + + @Override + protected boolean needsSave(Settings settings) { + if (super.needsSave(settings)) { + return true; + } + if (!generalSettings.toString().equals(settings.get(ConfigTags.SUTConnectorValue, ""))) { + return true; + } + return false; + } + + @Override + protected void save(Settings settings) { + super.save(settings); + settings.set(ConfigTags.SUTConnectorValue, generalSettings.toString()); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/child/MiscSettingsController.java b/testar/src/nl/ou/testar/jfx/settings/child/MiscSettingsController.java new file mode 100644 index 000000000..5150f248e --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/child/MiscSettingsController.java @@ -0,0 +1,315 @@ +package nl.ou.testar.jfx.settings.child; + +import javafx.beans.property.ReadOnlyObjectWrapper; +import javafx.scene.Parent; +import javafx.scene.control.*; +import javafx.scene.layout.HBox; +import javafx.stage.DirectoryChooser; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Pair; +import org.testar.monkey.Settings; +import nl.ou.testar.jfx.settings.bindings.ConfigBinding; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class MiscSettingsController extends SettingsEditController { + private Label labelOutDir; + private Label labelTmpDir; + + private TableView> copyTable; + private TableView deleteTable; + + private String outPath = settings.get(ConfigTags.OutputDir, ""); + private String tmpPath = settings.get(ConfigTags.TempDir, ""); + + public MiscSettingsController(Settings settings, String settingsPath) { + super("", settings, settingsPath); + } + + @Override + public void viewDidLoad(Parent view) { + super.viewDidLoad(view); + +// try { +// putSection(view, "Stub", "jfx/settings_stub.fxml"); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// if (true) return; + + try { + putSection(view, "Misc", "jfx/settings_misc.fxml", false); + putSection(view, "Files on SUT startup", "jfx/settings_startup.fxml", true); + if(isWebDriver(settings)) { + putSection(view, "Web settings", "jfx/settings_web.fxml", false); + } + } catch (IOException e) { + e.printStackTrace(); + } + + Button btnSelectOutDir = (Button) view.lookup("#btnSelectOutDir"); + Button btnSelectTmpDir = (Button) view.lookup("#btnSelectTmpDir"); + Button btnClearOut = (Button) view.lookup("#btnClearOut"); + Button btnClearTmp = (Button) view.lookup("#btnClearTmp"); + labelOutDir = (Label) view.lookup("#labelOutDir"); + labelTmpDir = (Label) view.lookup("#labelTmpDir"); + + btnClearOut.setOnAction(event -> { + outPath = null; + labelOutDir.setText("Not selected"); + btnClearOut.setDisable(true); + }); + + btnClearTmp.setOnAction(event -> { + tmpPath = null; + labelTmpDir.setText("Not selected"); + btnClearTmp.setDisable(true); + }); + + if (outPath != null && outPath.length() > 0) { + labelOutDir.setText("Selected: ".concat(outPath)); + btnClearOut.setDisable(false); + } + else { + labelOutDir.setText("Not selected"); + btnClearOut.setDisable(true); + } + + if (tmpPath != null && tmpPath.length() > 0) { + labelTmpDir.setText("Selected: ".concat(tmpPath)); + btnClearTmp.setDisable(false); + } + else { + labelTmpDir.setText("Not selected"); + btnClearTmp.setDisable(true); + } + + btnSelectOutDir.setOnAction(event -> { + DirectoryChooser outChooser = new DirectoryChooser(); + if (outPath != null && outPath.length() > 0) { + File outDir = new File(outPath); + if (outDir != null) { + outChooser.setInitialDirectory(outDir); + } + File newOutDir = outChooser.showDialog(view.getScene().getWindow()); + if (newOutDir != null) { + outPath = newOutDir.getAbsolutePath(); + labelOutDir.setText("Selected: ".concat(outPath)); + btnClearOut.setDisable(false); + } + } + }); + + btnSelectTmpDir.setOnAction(event -> { + DirectoryChooser tmpChooser = new DirectoryChooser(); + if (tmpPath != null && tmpPath.length() > 0) { + File tmpDir = new File(tmpPath); + if (tmpDir != null) { + tmpChooser.setInitialDirectory(tmpDir); + } + File newTmpDir = tmpChooser.showDialog(view.getScene().getWindow()); + if (newTmpDir != null) { + tmpPath = newTmpDir.getAbsolutePath(); + labelTmpDir.setText("Selected: ".concat(tmpPath)); + btnClearTmp.setDisable(false); + } + } + }); + + copyTable = (TableView) view.lookup("#copyTable"); + + TableColumn, String> copyFromColumn = (TableColumn, String>) copyTable.getColumns().get(0); + TableColumn, String> copyToColumn = (TableColumn, String>) copyTable.getColumns().get(1); + TableColumn, Void> copyToolsColumn = (TableColumn, Void>) copyTable.getColumns().get(2); + + copyToolsColumn.setCellFactory(column -> { + final TableCell, Void> cell = new TableCell, Void>() { + + @Override + public void updateItem(Void item, boolean empty) { + final int index = getIndex(); + final boolean isLast = (index == copyTable.getItems().size() - 1); + final Button btnEdit = new Button(isLast ? "Add" : "Edit"); + btnEdit.setStyle("-fx-font-size:10"); + + btnEdit.setOnAction(event -> { + Stage stage = (Stage) view.getScene().getWindow(); + + Pair itemValue = copyTable.getItems().get(index); + FileChooser srcChooser = new FileChooser(); + if (itemValue.left().length() > 0) { + File sourceFile = new File(itemValue.left()); + if (sourceFile != null) { + srcChooser.setInitialFileName(sourceFile.getAbsolutePath()); + } + } + String originalTitle = stage.getTitle(); + stage.setTitle("Select source file"); + + File newSourceFile = srcChooser.showOpenDialog(view.getScene().getWindow()); + + if (newSourceFile != null) { + DirectoryChooser dstChooser = new DirectoryChooser(); + if (itemValue.right().length() > 0) { + File destinatlonFile = new File(itemValue.right()); + if (destinatlonFile != null) { + dstChooser.setInitialDirectory(destinatlonFile); + } + } + stage.setTitle("Select destination"); + + File newDestinationFile = dstChooser.showDialog(view.getScene().getWindow()); + + if (newDestinationFile != null) { + copyTable.getItems().set(index, + new Pair<>(newSourceFile.getAbsolutePath(), newDestinationFile.getAbsolutePath())); + + if (isLast) { + copyTable.getItems().add(new Pair<>("", "")); + } + } + } + + stage.setTitle(originalTitle); + }); + + if (isLast) { + setGraphic(btnEdit); + } + else { + final Button btnDelete = new Button("Delete"); + btnDelete.setStyle("-fx-font-size:10"); + btnDelete.setOnAction(event -> { + copyTable.getItems().remove(index); + }); + + setGraphic(empty ? null : new HBox(btnEdit, btnDelete)); + } + } + }; + return cell; + }); + + copyFromColumn.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(data.getValue().left())); + copyToColumn.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(data.getValue().right())); + + copyTable.getItems().addAll(settings.get(ConfigTags.CopyFromTo)); + copyTable.getItems().add(new Pair("", "")); + + deleteTable = (TableView) view.lookup("#deleteTable"); + + TableColumn deleteColumn = (TableColumn) deleteTable.getColumns().get(0); + TableColumn deleteToolsColumn = (TableColumn) deleteTable.getColumns().get(1); + deleteColumn.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(data.getValue())); + + deleteTable.getItems().addAll(settings.get(ConfigTags.Delete, Collections.emptyList())); + deleteTable.getItems().add(""); + + deleteColumn.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(data.getValue())); + deleteToolsColumn.setCellFactory(column -> { + final TableCell cell = new TableCell() { + + @Override + public void updateItem(Void item, boolean empty) { + final int index = getIndex(); + final boolean isLast = (index == deleteTable.getItems().size() - 1); + + final Button btnEdit = new Button(isLast ? "Add" : "Edit"); + + btnEdit.setStyle("-fx-font-size:10"); + + btnEdit.setOnAction(event -> { + String itemValue = deleteTable.getItems().get(index); + FileChooser deleteChooser = new FileChooser(); + deleteChooser.setTitle("Delete file"); + if (itemValue.length() > 0) { + File file = new File(itemValue); + if (file != null) { + deleteChooser.setInitialFileName(file.getAbsolutePath()); + } + } + + File newFile = deleteChooser.showOpenDialog(view.getScene().getWindow()); + if (newFile != null) { + deleteTable.getItems().set(index, newFile.getAbsolutePath()); + + if (index == deleteTable.getItems().size() - 1) { + deleteTable.getItems().add(""); + } + } + }); + + if (isLast) { + setGraphic(btnEdit); + } + else { + final Button btnDelete = new Button("Delete"); + btnDelete.setStyle("-fx-font-size:10"); + btnDelete.setOnAction(event -> { + deleteTable.getItems().remove(index); + }); + setGraphic(empty ? null : new HBox(btnEdit, btnDelete)); + } + } + }; + return cell; + }); + + if(isWebDriver(settings)) { + CheckBox webFollowLinks = (CheckBox) view.lookup("#webFollowLinks"); + CheckBox webBrowserFullscreen = (CheckBox) view.lookup("#webBrowserFullscreen"); + CheckBox webSwitchNewTabs = (CheckBox) view.lookup("#webSwitchNewTabs"); + + addBinding(webFollowLinks, ConfigTags.FollowLinks, ConfigBinding.GenericType.CHECK_BOX); + addBinding(webBrowserFullscreen, ConfigTags.BrowserFullScreen, ConfigBinding.GenericType.CHECK_BOX); + addBinding(webSwitchNewTabs, ConfigTags.SwitchNewTabs, ConfigBinding.GenericType.CHECK_BOX); + } + } + + @Override + protected boolean needsSave(Settings settings) { + if (super.needsSave(settings)) { + return true; + } + if (outPath != null && !outPath.equals(settings.get(ConfigTags.OutputDir, ""))) { + return true; + } + if (tmpPath != null && !tmpPath.equals(settings.get(ConfigTags.TempDir, ""))) { + return true; + } + if (!itemsToCopy().equals(settings.get(ConfigTags.CopyFromTo, Collections.emptyList()))) { + return true; + } + if (!itemsToDelete().equals(settings.get(ConfigTags.Delete, Collections.emptyList()))) { + return true; + } + return false; + } + + @Override + protected void save(Settings settings) { + super.save(settings); + settings.set(ConfigTags.OutputDir, outPath); + settings.set(ConfigTags.TempDir, tmpPath); + settings.set(ConfigTags.CopyFromTo, itemsToCopy()); + settings.set(ConfigTags.Delete, itemsToDelete()); + } + + private boolean isWebDriver(Settings settings) { + return settings.get(ConfigTags.ProtocolClass, "").contains("webdriver"); + } + + private List> itemsToCopy() { + return copyTable.getItems().stream().filter(item -> item.left().length() > 0 && item.right().length() > 0).collect(Collectors.toList()); + } + + private List itemsToDelete() { + return deleteTable.getItems().stream().filter(item -> item.length() > 0).collect(Collectors.toList()); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/child/SettingsEditController.java b/testar/src/nl/ou/testar/jfx/settings/child/SettingsEditController.java new file mode 100644 index 000000000..826685f8d --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/child/SettingsEditController.java @@ -0,0 +1,156 @@ +package nl.ou.testar.jfx.settings.child; + +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.*; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import nl.ou.testar.jfx.core.ViewController; +import org.testar.extendedsettings.ExtendedSettingsFactory; +import org.testar.monkey.Main; +import org.testar.monkey.Settings; +import org.testar.monkey.Util; +import org.testar.monkey.alayer.Tag; +import org.testar.serialisation.LogSerialiser; +import nl.ou.testar.jfx.settings.bindings.ConfigBinding; +import nl.ou.testar.jfx.settings.bindings.ConfigBindingException; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +public abstract class SettingsEditController extends ViewController { + + private String settingsPath; + + private Set bindings; + + public SettingsEditController(String title, Settings settings, String settingsPath) { + super(title, "jfx/settings_child.fxml", settings); + bindings = new HashSet<>(); + this.settingsPath = settingsPath; + } + @Override + public void viewDidLoad(Parent view) { + super.viewDidLoad(view); + Button btnBack = (Button) view.lookup("#btnBack"); + btnBack.setOnAction(event -> { + getNavigationController().navigateBack(); + }); + Button btnSave = (Button) view.lookup("#btnSave"); + btnSave.setOnAction(event -> { + save(settings); + persist(settings); + getNavigationController().navigateBack(); + }); + } + + // TODO: put some docs + protected Parent putSection(Parent contentView, String title, String resourcePath, boolean stretchAllowed) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("jfx/settings_section.fxml")); + VBox sectionBox = (VBox) loader.load(); + + loader = new FXMLLoader(getClass().getClassLoader().getResource(resourcePath)); + Parent section = loader.load(); + VBox.setVgrow(section, stretchAllowed ? Priority.ALWAYS : Priority.NEVER); + sectionBox.getChildren().add(section); + + Label titleLabel = (Label) sectionBox.lookup("#titleLabel"); + titleLabel.setText(title); + +// AnchorPane contentPane = (AnchorPane) sectionBox.lookup("#contentPane"); +// contentPane.getChildren().add(contentView); +// AnchorPane.setLeftAnchor(contentView, 0.0); +// AnchorPane.setTopAnchor(contentView, 0.0); +// AnchorPane.setRightAnchor(contentView, 0.0); +// AnchorPane.setBottomAnchor(contentView, 0.0); + + VBox contentBox = (VBox) contentView.lookup("#contentBox"); + VBox.setVgrow(sectionBox, stretchAllowed ? Priority.ALWAYS : Priority.NEVER); + contentBox.getChildren().add(sectionBox); + + return section; + } + + protected Parent putSection(Parent contentView, String title, String resourcePath) throws IOException { + return putSection(contentView, title, resourcePath, true); + } + + protected boolean needsSave(Settings settings) { + for (ConfigBinding binding: bindings) { + if (binding.needsSave()) { + return true; + } + } + return false; + } + + protected void save(Settings settings) { + for (ConfigBinding binding: bindings) { + binding.save(); + } + } + + private void persist(Settings settings) { + ExtendedSettingsFactory.SaveAll(); + try { + Util.saveToFile(settings.toFileString(), settingsPath); + Settings.setSettingsPath(settingsPath.substring(0,settingsPath.indexOf(Main.SETTINGS_FILE)-1)); + System.out.println("Saved current settings to <" + settingsPath + ">"); + } catch (IOException e1) { + LogSerialiser.log("Unable to save current settings to <" + settingsPath + ">: " + e1.toString() + "\n"); + } + } + + @Override + public boolean checkBeforeExit() { + if (!needsSave(settings)) { + return true; + } + + Alert saveAlert = new Alert(Alert.AlertType.CONFIRMATION); + saveAlert.setTitle("Are you sure?"); + saveAlert.setHeaderText("There are unsaved changes"); + saveAlert.setContentText("Do you want to save them?"); + + ButtonType save = new ButtonType("Save"); + ButtonType discard = new ButtonType("Discard"); + ButtonType cancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); + + saveAlert.getButtonTypes().setAll(save, discard, cancel); + + Optional result = saveAlert.showAndWait(); + if (result.get() == save) { + save(settings); + return true; + } else if (result.get() == discard) { + return true; + } + + return false; + } + + protected void addBinding(ConfigBinding binding) { + binding.bind(); + bindings.add(binding); + } + + protected ConfigBinding addBinding(Control control, Tag tag, ConfigBinding.GenericType bindingType) { + ConfigBinding binding = null; + ConfigBinding.Builder builder = new ConfigBinding.Builder(); + try { + binding = builder + .withControl(control) + .withGenericType(bindingType) + .withSettings(settings) + .withTag(tag) + .build(); + addBinding(binding); + } catch (ConfigBindingException e) { + e.printStackTrace(); + } + return binding; + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/child/StateSettingsController.java b/testar/src/nl/ou/testar/jfx/settings/child/StateSettingsController.java new file mode 100644 index 000000000..173f08dfe --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/child/StateSettingsController.java @@ -0,0 +1,79 @@ +package nl.ou.testar.jfx.settings.child; + +import javafx.scene.Parent; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.TextField; +import javafx.stage.DirectoryChooser; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Settings; +import nl.ou.testar.jfx.settings.bindings.ConfigBinding; + +import java.io.File; +import java.io.IOException; + +public class StateSettingsController extends SettingsEditController { + + private Button selectDir; + + public StateSettingsController(Settings settings, String settingsPath) { + super("", settings, settingsPath); + } + + @Override + public void viewDidLoad(Parent view) { + super.viewDidLoad(view); + try { + putSection(view, "State", "jfx/settings_state.fxml"); + putSection(view, "Widgets", "jfx/settings_widgets.fxml"); + } catch (IOException e) { + e.printStackTrace(); + } + + TextField dataStore = (TextField) view.lookup("#dataStore"); + TextField dataStoreDB = (TextField) view.lookup("#dataStoreDB"); + ComboBox dataStoreType = (ComboBox) view.lookup("#dataStoreType"); + TextField dataStoreUser = (TextField) view.lookup("#dataStoreUser"); + TextField dataStoreServer = (TextField) view.lookup("#dataStoreServer"); + TextField dataStorePassword = (TextField) view.lookup("#dataStorePassword"); + TextField dataStoreDirectory = (TextField) view.lookup("#dataStoreDirectory"); + ComboBox dataStoreMode = (ComboBox) view.lookup("#dataStoreMode"); + selectDir = (Button) view.lookup("#selectDir"); + + CheckBox storeWidgets = (CheckBox) view.lookup("#storeWidgets"); + CheckBox accessbridgeEnabled = (CheckBox) view.lookup("#accessbridgeEnabled"); + CheckBox resetDatabase = (CheckBox) view.lookup("#resetDatabase"); + + dataStoreType.getItems().addAll("remote", "plocal"); + dataStoreMode.getItems().addAll("none", "instant", "delayed", "hybrid"); + + addBinding(dataStore, ConfigTags.DataStore, ConfigBinding.GenericType.FIELD_STRING); + addBinding(dataStoreDB, ConfigTags.DataStoreDB, ConfigBinding.GenericType.FIELD_STRING); + addBinding(dataStoreType, ConfigTags.DataStoreType, ConfigBinding.GenericType.COMBO_BOX); + addBinding(dataStoreUser, ConfigTags.DataStoreUser, ConfigBinding.GenericType.FIELD_STRING); + addBinding(dataStoreServer, ConfigTags.DataStoreServer, ConfigBinding.GenericType.FIELD_STRING); + addBinding(dataStorePassword, ConfigTags.DataStorePassword, ConfigBinding.GenericType.FIELD_STRING); + addBinding(dataStoreMode, ConfigTags.DataStoreMode, ConfigBinding.GenericType.COMBO_BOX); + addBinding(storeWidgets, ConfigTags.StateModelStoreWidgets, ConfigBinding.GenericType.CHECK_BOX); + addBinding(accessbridgeEnabled, ConfigTags.AccessBridgeEnabled, ConfigBinding.GenericType.CHECK_BOX); + addBinding(resetDatabase, ConfigTags.ResetDataStore, ConfigBinding.GenericType.CHECK_BOX); + + ConfigBinding dataStoreDirectoryBinding = addBinding(dataStoreDirectory, ConfigTags.DataStoreDirectory, ConfigBinding.GenericType.FIELD_STRING); + + selectDir.setOnAction(event -> { + String path = dataStoreDirectory.getText(); + DirectoryChooser chooser = new DirectoryChooser(); + if (path.length() > 0) { + File dir = new File(path); + if (dir != null) { + chooser.setInitialDirectory(dir); + } + } + final File newDir = chooser.showDialog(view.getScene().getWindow()); + if (newDir != null) { + dataStoreDirectoryBinding.setValue(newDir.getAbsolutePath()); + } + }); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/child/TimeSettingsController.java b/testar/src/nl/ou/testar/jfx/settings/child/TimeSettingsController.java new file mode 100644 index 000000000..e4ad60baa --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/child/TimeSettingsController.java @@ -0,0 +1,59 @@ +package nl.ou.testar.jfx.settings.child; + +import javafx.scene.Parent; +import javafx.scene.control.CheckBox; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Settings; +import javafx.scene.control.TextField; +import nl.ou.testar.jfx.settings.bindings.ConfigBinding; + +import java.io.IOException; + +public class TimeSettingsController extends SettingsEditController { + + private CheckBox useRecordTimingCheckbox; + + public TimeSettingsController(Settings settings, String settingsPath) { + super("Time settings", settings, settingsPath); + } + + @Override + public void viewDidLoad(Parent view) { + super.viewDidLoad(view); + try { + putSection(view, "Time settings", "jfx/settings_time.fxml"); + } catch (IOException e) { + e.printStackTrace(); + } + + TextField actionDurationField = (TextField) view.lookup("#actionDuration"); + TextField waitTimeField = (TextField) view.lookup("#waitTime"); + TextField startupTimeField = (TextField) view.lookup("#startupTime"); + TextField maxTestTimeField = (TextField) view.lookup("#maxTestTime"); + + useRecordTimingCheckbox = (CheckBox) view.lookup("#useRecordTiming"); + useRecordTimingCheckbox.setSelected(settings.get(ConfigTags.UseRecordedActionDurationAndWaitTimeDuringReplay, false)); + + addBinding(actionDurationField, ConfigTags.ActionDuration, ConfigBinding.GenericType.FIELD_DOUBLE); + addBinding(waitTimeField, ConfigTags.TimeToWaitAfterAction, ConfigBinding.GenericType.FIELD_DOUBLE); + addBinding(startupTimeField, ConfigTags.StartupTime, ConfigBinding.GenericType.FIELD_DOUBLE); + addBinding(maxTestTimeField, ConfigTags.MaxTime, ConfigBinding.GenericType.FIELD_DOUBLE); + } + + @Override + protected boolean needsSave(Settings settings) { + if (super.needsSave(settings)) { + return true; + } + if (useRecordTimingCheckbox.isSelected() != settings.get(ConfigTags.UseRecordedActionDurationAndWaitTimeDuringReplay, false)) { + return true; + } + return false; + } + + @Override + protected void save(Settings settings) { + super.save(settings); + settings.set(ConfigTags.UseRecordedActionDurationAndWaitTimeDuringReplay, useRecordTimingCheckbox.isSelected()); + } +} diff --git a/testar/src/nl/ou/testar/jfx/settings/child/WhiteboxSettingsController.java b/testar/src/nl/ou/testar/jfx/settings/child/WhiteboxSettingsController.java new file mode 100644 index 000000000..59ef373e8 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/settings/child/WhiteboxSettingsController.java @@ -0,0 +1,154 @@ +package nl.ou.testar.jfx.settings.child; + +import javafx.scene.Parent; +import javafx.scene.control.CheckBox; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import org.testar.monkey.ConfigTags; +import org.testar.monkey.Settings; +import nl.ou.testar.jfx.settings.bindings.ConfigBinding; +import nl.ou.testar.jfx.settings.bindings.ConfigBindingException; +import nl.ou.testar.jfx.settings.bindings.control.ControlBinding; + +import java.io.IOException; + +public class WhiteboxSettingsController extends SettingsEditController { + + private TextField gitUsernameField; + private TextField gitTokenField; + + private TextField sonarUrlField; + private TextField sonarUsernameField; + private TextField sonarPasswordField; + + public WhiteboxSettingsController(Settings settings, String settingsPath) { + super("Whitebox", settings, settingsPath); + } + + @Override + public void viewDidLoad(Parent view) { + super.viewDidLoad(view); + try { + putSection(view, "Git", "jfx/settings_git.fxml", false); + putSection(view, "Sonarqube service", "jfx/settings_sonarqube.fxml", false); + putSection(view, "Sonarqube project", "jfx/settings_sonar_project.fxml", true); + } + catch (IOException e) { + e.printStackTrace(); + } + + TextField gitUrlField = (TextField) view.lookup("#gitUrl"); + gitUsernameField = (TextField) view.lookup("#gitUsername"); + gitTokenField = (TextField) view.lookup("#gitToken"); + TextField gitBranchField = (TextField) view.lookup("#gitBranch"); + + final CheckBox gitAuthorizationRequiredBox = (CheckBox) view.lookup("#authorizationRequired"); + + sonarUrlField = (TextField) view.lookup("#sonarUrl"); + sonarUsernameField = (TextField) view.lookup("#sonarUsername"); + sonarPasswordField = (TextField) view.lookup("#sonarPassword"); + + CheckBox sonarDockerizeBox = (CheckBox) view.lookup("#sonarDockerize"); + + TextArea sonarProjectPropertiesArea = (TextArea) view.lookup("#sonarProjectProperties"); + TextField sonarProjectNameField = (TextField) view.lookup("#sonarProjectName"); + TextField sonarProjectKeyField = (TextField) view.lookup("#sonarProjectKey"); + CheckBox sonarSaveResultBox = (CheckBox) view.lookup("#sonarSaveResult"); + + addBinding(gitUrlField, ConfigTags.GitUrl, ConfigBinding.GenericType.FIELD_STRING); + addBinding(gitUsernameField, ConfigTags.GitUsername, ConfigBinding.GenericType.FIELD_STRING); + addBinding(gitTokenField, ConfigTags.GitToken, ConfigBinding.GenericType.FIELD_STRING); + addBinding(gitBranchField, ConfigTags.GitBranch, ConfigBinding.GenericType.FIELD_STRING); + addBinding(sonarUrlField, ConfigTags.SonarUrl, ConfigBinding.GenericType.FIELD_STRING); + addBinding(sonarUsernameField, ConfigTags.SonarUsername, ConfigBinding.GenericType.FIELD_STRING); + addBinding(sonarPasswordField, ConfigTags.SonarPassword, ConfigBinding.GenericType.FIELD_STRING); + addBinding(sonarProjectPropertiesArea, ConfigTags.SonarProjectProperties, ConfigBinding.GenericType.TEXT_INPUT); + addBinding(sonarProjectNameField, ConfigTags.SonarProjectName, ConfigBinding.GenericType.FIELD_STRING); + addBinding(sonarProjectKeyField, ConfigTags.SonarProjectKey, ConfigBinding.GenericType.FIELD_STRING); + addBinding(sonarSaveResultBox, ConfigTags.SonarSaveResult, ConfigBinding.GenericType.CHECK_BOX); + + ControlBinding gitAuthorizationRequiredControlBinding = new ControlBinding() { + @Override + public void setValue(Boolean value) { + gitAuthorizationRequiredBox.setSelected(value); + updateGitFields(value); + } + + @Override + public Boolean getValue() { + return gitAuthorizationRequiredBox.isSelected(); + } + + @Override + public void onBind(Callback callback) { + gitAuthorizationRequiredBox.selectedProperty().addListener((observable, oldValue, newValue) -> { + callback.onUpdate(newValue); + }); + } + }; + try { + ConfigBinding gitAuthorizationRequiredConfigBinding = new ConfigBinding.Builder() + .withCustomControlBinding(gitAuthorizationRequiredControlBinding) + .withSettings(settings) + .withTag(ConfigTags.GitAuthRequired) + .withGenericType(ConfigBinding.GenericType.CHECK_BOX) + .build(); + addBinding(gitAuthorizationRequiredConfigBinding); + } catch (ConfigBindingException e) { + e.printStackTrace(); + } + + ControlBinding sonarDockerizeControlBinding = new ControlBinding() { + + @Override + public void setValue(Boolean value) { + System.out.println("Dockerize: " + value.toString()); + sonarDockerizeBox.setSelected(value); + updateSonarFields(value); + } + + @Override + public Boolean getValue() { + return sonarDockerizeBox.isSelected(); + } + + @Override + public void onBind(Callback callback) { + sonarDockerizeBox.selectedProperty().addListener((observable, oldValue, newValue) -> { + callback.onUpdate(newValue); + }); + } + }; + ConfigBinding sonarDockerizeConfigBinding = null; + try { + sonarDockerizeConfigBinding = new ConfigBinding.Builder() + .withCustomControlBinding(sonarDockerizeControlBinding) + .withSettings(settings) + .withTag(ConfigTags.SonarDockerize) + .withGenericType(ConfigBinding.GenericType.CHECK_BOX) + .build(); + addBinding(sonarDockerizeConfigBinding); + } catch (ConfigBindingException e) { + e.printStackTrace(); + } + } + + private void updateGitFields(boolean authorizationRequired) { + gitUsernameField.setDisable(!authorizationRequired); + gitTokenField.setDisable(!authorizationRequired); + } + + private void updateSonarFields(boolean dockerEnabled) { + if (dockerEnabled) { + sonarUrlField.setDisable(true); + sonarUsernameField.setDisable(true); + sonarPasswordField.setDisable(true); + } + else { + sonarUrlField.setDisable(false); + sonarUsernameField.setDisable(false); + sonarPasswordField.setDisable(false); + + } + } +} diff --git a/testar/src/nl/ou/testar/jfx/thirdparty/DisplayShelf.java b/testar/src/nl/ou/testar/jfx/thirdparty/DisplayShelf.java new file mode 100644 index 000000000..8c5cb7dde --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/thirdparty/DisplayShelf.java @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2008, 2013 Oracle and/or its affiliates. + * All rights reserved. Use is subject to license terms. + * + * This file is available and licensed under the following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * - Neither the name of Oracle Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package nl.ou.testar.jfx.thirdparty; + +import javafx.animation.Interpolator; +import javafx.animation.KeyFrame; +import javafx.animation.KeyValue; +import javafx.animation.Timeline; +import javafx.application.Platform; +import javafx.collections.ObservableList; +import javafx.event.EventHandler; +import javafx.scene.Group; +import javafx.scene.Node; +import javafx.scene.image.Image; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Region; +import javafx.scene.shape.Rectangle; +import javafx.util.Duration; + +/** + * Simple 7 segment LED style digit. It supports the numbers 0 through 9. + */ +/** + * A ui control which displays a browsable display shelf of images + */ +public class DisplayShelf extends Region { + + // Added more duration constant (IVS-150) + // @author Michael Tikhonenko (Marviq B.V) + private final Duration NORMAL_DURATION = Duration.millis(500); + private final Duration LONG_DURATION = Duration.millis(2000); + private final Duration SHORT_DURATION = Duration.millis(250); + private final int SLOW_SCROLL_MILLIS = 2100; + // End of changes by IVS-150 + + private final Interpolator INTERPOLATOR = Interpolator.EASE_BOTH; + private final double LEFT_OFFSET = -110; + private final double RIGHT_OFFSET = 110; + private PerspectiveImage[] items; + private Group centered = new Group(); + private Group left = new Group(); + private Group center = new Group(); + private Group right = new Group(); + private int centerIndex = 0; + private Timeline timeline; + + // Scroll bar has been removed + // @author Michael Tikhonenko (Marviq B.V) + + private Rectangle clip = new Rectangle(); + + // These settings were modified in tickets IVS-128, IVS-150 + // Also added some extra variables and a simple helper method + // for scrolling + // @author Michael Tikhonenko (Marviq B.V) + private final double SPACING = 100; + private final double SCALE_LARGE = 0.9; + private final double SCALE_SMALL = 0.5; + private final double TOP_OFFSET = 80; + private final double ASPECT_RATIO = 0.25; + private final double MAX_MOUSE_OFFSET = 200; + private final int SIDE_ITEMS_COUNT = 2; + private final int BUFFER_ITEMS_COUNT = 2; + + private int itemsCount = 0; + private double pressedX; + private boolean autoScrollActive = true; + + private void scrollTo(int pos, Duration duration) { + shiftToCenter(items[pos], duration); + } + // End of changes by IVS-128, IVS 150 + + // The constructor is substantially modified to loop scroll + // and do without a scroll bar (IVS-150) + // @author Michael Tikhonenko (Marviq B.V) + public DisplayShelf(Image[] images) { + + // set clip + setClip(clip); + + // create items + int displayableCount = 2 * (SIDE_ITEMS_COUNT + BUFFER_ITEMS_COUNT) + 1; + itemsCount = images.length * ((displayableCount - 1) / images.length + 1); + items = new PerspectiveImage[itemsCount]; + int j = 0; + for (int i = 0; i < itemsCount; i++) { + final PerspectiveImage item = + items[i] = new PerspectiveImage(images[j]); + final int index = j; + item.setOnMouseClicked(new EventHandler() { + @Override + public void handle(MouseEvent me) { + scrollTo(index, NORMAL_DURATION); + } + }); + + item.setAngle(90); + + if (++j >= images.length) { + j = 0; + } + } + + // create content + centered.getChildren().addAll(left, center, right); + getChildren().addAll(centered/*, scrollBar*/); + // listen for keyboard events + setFocusTraversable(true); + setOnKeyPressed(new EventHandler() { + @Override + public void handle(KeyEvent ke) { + if (ke.getCode() == KeyCode.LEFT) { + int target = centerIndex + 1; + if (target >= itemsCount) { + target -= itemsCount; + } + scrollTo(target, NORMAL_DURATION); + } else if (ke.getCode() == KeyCode.RIGHT) { + int target = centerIndex - 1; + if (target < 0) { + target += itemsCount; + } + scrollTo(target, NORMAL_DURATION); + } + } + }); + + // Next 4 methods enable panning with mouse + setOnMousePressed(event -> { + pressedX = event.getX(); + autoScrollActive = false; + update(0, SHORT_DURATION); + }); + + setOnMouseReleased(event -> { + autoScrollActive = true; + }); + + setOnMouseDragged(event -> { + Double offset = event.getX() - pressedX; + if (offset < -MAX_MOUSE_OFFSET) { + offset = -MAX_MOUSE_OFFSET; + } + else if (offset > MAX_MOUSE_OFFSET) { + offset = MAX_MOUSE_OFFSET; + } + while (offset >= SPACING) { + offset -= SPACING; + pressedX += SPACING; + int newCenterIndex = centerIndex - 1; + if (newCenterIndex < 0) { + newCenterIndex += itemsCount; + } + scrollTo(newCenterIndex, NORMAL_DURATION); + } + while (offset < -SPACING) { + offset += SPACING; + pressedX -= SPACING; + int newCenterIndex = centerIndex + 1; + if (newCenterIndex >= itemsCount) { + newCenterIndex -= itemsCount; + } + scrollTo(newCenterIndex, NORMAL_DURATION); + } + }); + + // update + update(); + + // Starting auto scroll + final Thread autoScrollThread = new Thread(() -> { + do { + try { + Thread.sleep(SLOW_SCROLL_MILLIS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (autoScrollActive) { + Platform.runLater(() -> { + int target = centerIndex - 1; + if (target < 0) { + target += itemsCount; + } + scrollTo(target, LONG_DURATION); + }); + } + } while (true); + }); + autoScrollThread.start(); + } + // End of changes by IVS-128, IVS 150 + + @Override + protected void layoutChildren() { + + // update clip to our size + clip.setWidth(getWidth()); + clip.setHeight(getHeight()); + // keep centered centered + centered.setLayoutY((getHeight() - PerspectiveImage.HEIGHT) / 2); + centered.setLayoutX((getWidth() - PerspectiveImage.WIDTH) / 2); + + // Scroll bar has been removed + // @author Michael Tikhonenko (Marviq B.V) + } + + // Update and shift code substantially modified (IVS-150) + // @author Michael Tikhonenko (Marviq B.V) + private void update() { + update(0, NORMAL_DURATION); + } + + private void update(int shiftAmount) { + update(shiftAmount, NORMAL_DURATION); + } + + private void update(int shiftAmount, Duration duration) { + // move items to new homes in groups + left.getChildren().clear(); + center.getChildren().clear(); + right.getChildren().clear(); + + int leftItemsCount = SIDE_ITEMS_COUNT; + int rightItemsCount = SIDE_ITEMS_COUNT; + leftItemsCount += BUFFER_ITEMS_COUNT; + rightItemsCount += BUFFER_ITEMS_COUNT;//shiftAmount; + + int index = itemsCount + centerIndex - leftItemsCount; + if (index < 0) { + index += itemsCount; + } + for (int i = 0; i < leftItemsCount; i++) { + if (index >= itemsCount) { + index -= itemsCount; + } + left.getChildren().add(items[index++]); + }; + + center.getChildren().add(items[centerIndex]); + + index = centerIndex + 1; + for (int i = 0; i < rightItemsCount; i++) { + if (index >= itemsCount) { + index = 0; + } + right.getChildren().add(items[index++]); + } + + // stop old timeline if there is one running + if (timeline != null) { + timeline.stop(); + } + // create timeline to animate to new positions + timeline = new Timeline(); + // add keyframes for left items + final ObservableList keyFrames = timeline.getKeyFrames(); + ObservableList leftItems = left.getChildren(); + + for (int i = 0; i < leftItemsCount; i++) { + final PerspectiveImage it = (PerspectiveImage)leftItems.get(i);//items[i]; + boolean isHidden = false; + if (shiftAmount > 0 && i <= 2) { + it.setTranslateX(-left.getChildren().size() + * SPACING + SPACING + LEFT_OFFSET); + it.setTranslateY(TOP_OFFSET); + it.setScaleX(SCALE_SMALL); + it.setScaleY(ASPECT_RATIO * SCALE_SMALL); + it.setAngle(45.0); + it.setOpacity(0.0); + isHidden = (i < 2); + } + else if (shiftAmount < 0 && i < 2) { + isHidden = true; + } + + double newX = -left.getChildren().size() + * SPACING + SPACING * i + LEFT_OFFSET; + + keyFrames.add(new KeyFrame(duration, + // These settings were changed/added in ticket IVS-128 to conform our style + // @author Michael Tikhonenko (Marviq B.V) + new KeyValue(it.translateXProperty(), newX, INTERPOLATOR), + new KeyValue(it.translateYProperty(), TOP_OFFSET, INTERPOLATOR), + new KeyValue(it.scaleXProperty(), SCALE_SMALL, INTERPOLATOR), + new KeyValue(it.scaleYProperty(), ASPECT_RATIO * SCALE_SMALL, INTERPOLATOR), + // End of changes by IVS-128 + new KeyValue(it.angle, 45.0, INTERPOLATOR), + new KeyValue(it.opacityProperty(), (isHidden ? 0.0 : 1.0), INTERPOLATOR))); + } + // add keyframe for center item + final PerspectiveImage centerItem = items[centerIndex]; + keyFrames.add(new KeyFrame(duration, + // These settings were changed/added in ticket IVS-128 to conform our style + // @author Michael Tikhonenko (Marviq B.V) + new KeyValue(centerItem.translateXProperty(), 0, INTERPOLATOR), + new KeyValue(centerItem.translateYProperty(), TOP_OFFSET, INTERPOLATOR), + new KeyValue(centerItem.scaleXProperty(), SCALE_LARGE, INTERPOLATOR), + new KeyValue(centerItem.scaleYProperty(), ASPECT_RATIO * SCALE_LARGE, INTERPOLATOR), + // End of changes by IVS-128 + new KeyValue(centerItem.angle, 90.0, INTERPOLATOR), + new KeyValue(centerItem.opacityProperty(), 1.0, INTERPOLATOR))); + // add keyframes for right items + ObservableList rightItems = right.getChildren(); + for (int i = 0; i < rightItemsCount; i++) { + final PerspectiveImage it = (PerspectiveImage) rightItems.get(i); + boolean isHidden = false; + if (shiftAmount < 0 && i >= SIDE_ITEMS_COUNT - 1) { + it.setTranslateX(rightItems.size() + * SPACING - SPACING + RIGHT_OFFSET); + it.setTranslateY(TOP_OFFSET); + it.setScaleX(SCALE_SMALL); + it.setScaleY(ASPECT_RATIO * SCALE_SMALL); + it.setAngle(135.0); + it.setOpacity(0.0); + isHidden = (i > SIDE_ITEMS_COUNT - 1); + } + else if (shiftAmount > 0 && i >= SIDE_ITEMS_COUNT) { + isHidden = true; + } + + final double newX = rightItems.size() + * SPACING - SPACING * (rightItemsCount - i - 1) + RIGHT_OFFSET; + keyFrames.add(new KeyFrame(duration, + // These settings were changed/added in ticket IVS-128 to conform our style + // @author Michael Tikhonenko (Marviq B.V) + new KeyValue(it.translateXProperty(), newX, INTERPOLATOR), + new KeyValue(it.translateYProperty(), TOP_OFFSET, INTERPOLATOR), + new KeyValue(it.scaleXProperty(), SCALE_SMALL, INTERPOLATOR), + new KeyValue(it.scaleYProperty(), ASPECT_RATIO * SCALE_SMALL, INTERPOLATOR), + // End of changes by IVS-128 + new KeyValue(it.angle, 135.0, INTERPOLATOR), + new KeyValue(it.opacityProperty(), (isHidden ? 0.0 : 1.0), INTERPOLATOR))); + } + // play animation + timeline.play(); + } + + // A simple helper method + + private void shiftToCenter(PerspectiveImage item, Duration duration) { + int index = 0; + for (PerspectiveImage _item: items) { + if (_item == item) { + shift(centerIndex - index, duration); + return; + } + index++; + } + } + + public void shift(int shiftAmount, Duration duration) { + if (shiftAmount <= -itemsCount + 1) { + shiftAmount += itemsCount; + } + else if (shiftAmount >= itemsCount - 1) { + shiftAmount -= itemsCount; + } + + centerIndex -= shiftAmount; + if (centerIndex < 0) { + centerIndex += itemsCount; + } + else if (centerIndex >= itemsCount) { + centerIndex -= itemsCount; + } + update(shiftAmount, duration); + } + // End of changes by IVS-128, IVS 150 +} \ No newline at end of file diff --git a/testar/src/nl/ou/testar/jfx/thirdparty/PerspectiveImage.java b/testar/src/nl/ou/testar/jfx/thirdparty/PerspectiveImage.java new file mode 100644 index 000000000..6e1d7a105 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/thirdparty/PerspectiveImage.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008, 2013 Oracle and/or its affiliates. + * All rights reserved. Use is subject to license terms. + * + * This file is available and licensed under the following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * - Neither the name of Oracle Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package nl.ou.testar.jfx.thirdparty; + +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.scene.Parent; +import javafx.scene.effect.PerspectiveTransform; +import javafx.scene.effect.ReflectionBuilder; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +/** + * A Node that displays a image with some 2.5D perspective rotation around the Y + * axis. + */ +public class PerspectiveImage extends Parent { + + private static final double REFLECTION_SIZE = 0.25; + + // Width modified for our needs + // @author Michael Tikhonenko (Marviq B.V) + public static final double WIDTH = 200; + + public static final double HEIGHT = WIDTH + (WIDTH * REFLECTION_SIZE); + + private static final double RADIUS_H = WIDTH / 2; + private static final double BACK = WIDTH / 10; + private PerspectiveTransform transform = new PerspectiveTransform(); + /** + * Angle Property + */ + public final DoubleProperty angle = new SimpleDoubleProperty(45) { + @Override + protected void invalidated() { + // when angle changes calculate new transform + double lx = (RADIUS_H - Math.sin(Math.toRadians(angle.get())) * RADIUS_H - 1); + double rx = (RADIUS_H + Math.sin(Math.toRadians(angle.get())) * RADIUS_H + 1); + double uly = (-Math.cos(Math.toRadians(angle.get())) * BACK); + double ury = -uly; + transform.setUlx(lx); + transform.setUly(uly); + transform.setUrx(rx); + transform.setUry(ury); + transform.setLrx(rx); + transform.setLry(HEIGHT + uly); + transform.setLlx(lx); + transform.setLly(HEIGHT + ury); + } + }; + + public final double getAngle() { + return angle.getValue(); + } + + public final void setAngle(double value) { + angle.setValue(value); + } + + public final DoubleProperty angleModel() { + return angle; + } + + public PerspectiveImage(Image image) { + ImageView imageView = new ImageView(image); + imageView.setEffect(ReflectionBuilder.create().fraction(REFLECTION_SIZE).build()); + setEffect(transform); + getChildren().addAll(imageView); + } +} \ No newline at end of file diff --git a/testar/src/nl/ou/testar/jfx/utils/DisplayModeWrapper.java b/testar/src/nl/ou/testar/jfx/utils/DisplayModeWrapper.java new file mode 100644 index 000000000..be7ed54bd --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/utils/DisplayModeWrapper.java @@ -0,0 +1,43 @@ +package nl.ou.testar.jfx.utils; + +import java.awt.DisplayMode; + +public class DisplayModeWrapper { + + private final DisplayMode mode; + private final boolean supported; + + public DisplayModeWrapper(DisplayMode mode, boolean supported) { + this.mode = mode; + this.supported = supported; + }; + + public DisplayMode getMode() { + return mode; + } + + public boolean isSupported() { + return supported; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof DisplayModeWrapper)) { + return false; + } + DisplayModeWrapper wrapper = (DisplayModeWrapper) obj; + return (mode.getWidth() == wrapper.mode.getWidth() && mode.getHeight() == wrapper.mode.getHeight()); + } + + @Override + public String toString() { + String result = String.format("%dx%d", mode.getWidth(), mode.getHeight()); + if (!supported) { + result = result.concat(" (not supported)"); + } + return result; + } +} diff --git a/testar/src/nl/ou/testar/jfx/utils/GeneralSettings.java b/testar/src/nl/ou/testar/jfx/utils/GeneralSettings.java new file mode 100644 index 000000000..abebbdbd7 --- /dev/null +++ b/testar/src/nl/ou/testar/jfx/utils/GeneralSettings.java @@ -0,0 +1,71 @@ +package nl.ou.testar.jfx.utils; + +import java.awt.DisplayMode; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class GeneralSettings { + + private String source; + private String driver; + private String location; + private DisplayMode displayMode; + + private final static String TEMPLATE = "\"([^\"]*)\"\\s+\"(\\d+)x(\\d+)\\+(\\d+)\\+(\\d+)\"\\s+\"([^\"]*)\""; + private final static String FORMAT = "\"%s\" \"%dx%d+%d+%d\" \"%s\""; + + public GeneralSettings(String source, DisplayMode fallbackDisplayMode) { + this.source = source; + Pattern pattern = Pattern.compile(TEMPLATE); + Matcher matcher = pattern.matcher(source); + if (matcher.find()) { + driver = matcher.group(1); + location = matcher.group(6); + + int width = Integer.parseInt(matcher.group(2)); + int height = Integer.parseInt(matcher.group(3)); + int bitDepth = Integer.parseInt(matcher.group(4)); + int refreshRate = Integer.parseInt(matcher.group(5)); + displayMode = new DisplayMode(width, height, bitDepth, refreshRate); + } + else { + driver = ""; + location = ""; + displayMode = fallbackDisplayMode; + } + } + + public String getSource() { + return source; + } + + public String getDriver() { + return driver; + } + + public void setDriver(String driver) { + this.driver = driver; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public DisplayMode getDisplayMode() { + return displayMode; + } + + public void setDisplayMode(DisplayMode displayMode) { + this.displayMode = displayMode; + } + + @Override + public String toString() { + return String.format(FORMAT, driver, displayMode.getWidth(), displayMode.getHeight(), + displayMode.getBitDepth(), displayMode.getRefreshRate(), location); + } +} diff --git a/testar/src/org/fruit/monkey/ProtocolDelegate.java b/testar/src/org/fruit/monkey/ProtocolDelegate.java new file mode 100644 index 000000000..475c190b8 --- /dev/null +++ b/testar/src/org/fruit/monkey/ProtocolDelegate.java @@ -0,0 +1,8 @@ +package org.fruit.monkey; + +import java.net.URI; + +public interface ProtocolDelegate { + void popupMessage(String message); + void openURI(URI uri); +} diff --git a/testar/src/org/fruit/monkey/docker/DockerPoolServiceDelegate.java b/testar/src/org/fruit/monkey/docker/DockerPoolServiceDelegate.java new file mode 100644 index 000000000..3ba3fbedc --- /dev/null +++ b/testar/src/org/fruit/monkey/docker/DockerPoolServiceDelegate.java @@ -0,0 +1,5 @@ +package org.fruit.monkey.docker; + +public interface DockerPoolServiceDelegate { + void onStatusChange(String statusDescripton, Long currentPorgress, long totalProgress); +} diff --git a/testar/src/org/fruit/monkey/jfx/SettingsDialogJFX.java b/testar/src/org/fruit/monkey/jfx/SettingsDialogJFX.java new file mode 100644 index 000000000..502ac6e61 --- /dev/null +++ b/testar/src/org/fruit/monkey/jfx/SettingsDialogJFX.java @@ -0,0 +1,11 @@ +package org.fruit.monkey.jfx; + +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.paint.Color; + +public class SettingsDialogJFX extends Scene { + public SettingsDialogJFX(Parent root) { + super(root); + } +} diff --git a/testar/src/org/testar/managers/FilteringManager.java b/testar/src/org/testar/managers/FilteringManager.java index adcb0c631..e444250fe 100644 --- a/testar/src/org/testar/managers/FilteringManager.java +++ b/testar/src/org/testar/managers/FilteringManager.java @@ -369,12 +369,13 @@ public void setWidgetFilter (State state, Mouse mouse, boolean preciseCoding) return; } Object[] options = DataManager.DATA_TYPES.keySet().toArray(); - String s = (String) JOptionPane.showInputDialog(new JFrame(), "Input values:", "Widget input value type", - JOptionPane.PLAIN_MESSAGE, null, options, options[0]); - if (DataManager.DATA_TYPES.containsKey(s)) { - filterLists(cursorWidget, DataManager.DATA_TYPES.get(s), preciseCoding ? CodingManager.ABSTRACT_R_T_P_ID : CodingManager.ABSTRACT_R_T_ID); - saveFilters(); - } + // TODO: show input widget +// String s = (String) JOptionPane.showInputDialog(new JFrame(), "Input values:", "Widget input value type", +// JOptionPane.PLAIN_MESSAGE, null, options, options[0]); +// if (DataManager.DATA_TYPES.containsKey(s)) { +// filterLists(cursorWidget, DataManager.DATA_TYPES.get(s), preciseCoding ? CodingManager.ABSTRACT_R_T_P_ID : CodingManager.ABSTRACT_R_T_ID); +// saveFilters(); +// } } public boolean blackListed (Widget w) diff --git a/testar/src/org/testar/monkey/ConfigTags.java b/testar/src/org/testar/monkey/ConfigTags.java index 5eec9d38b..de3151205 100644 --- a/testar/src/org/testar/monkey/ConfigTags.java +++ b/testar/src/org/testar/monkey/ConfigTags.java @@ -3,7 +3,7 @@ * Copyright (c) 2013 - 2021 Universitat Politecnica de Valencia - www.upv.es * Copyright (c) 2018 - 2021 Open Universiteit - www.ou.nl * -* Redistribution and use in source and binary forms, with or without +* Redistribution an d use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, @@ -150,6 +150,21 @@ public final class ConfigTags { public static final Tag FlashFeedback = Tag.from("FlashFeedback", Boolean.class); public static final Tag ProtocolCompileDirectory = Tag.from("ProtocolCompileDirectory", String.class); public static final Tag ReportingClass = Tag.from("ReportingClass", String.class); + public static final Tag GitUrl = Tag.from("GitUrl", String.class); + public static final Tag GitUsername = Tag.from("GitUsername", String.class); + public static final Tag GitToken = Tag.from("GitToken", String.class); + public static final Tag GitBranch = Tag.from("GitBranch", String.class); + public static final Tag GitAuthRequired = Tag.from("GitAuthRequired", Boolean.class); + + public static final Tag SonarUrl = Tag.from("SonarUrl", String.class); + public static final Tag SonarUsername = Tag.from("SonarUsername", String.class); + public static final Tag SonarPassword = Tag.from("SonarPassword", String.class); + public static final Tag SonarDockerize = Tag.from("SonarDockerize", Boolean.class); + public static final Tag SonarSaveResult = Tag.from("SonarSaveResult", Boolean.class); + + public static final Tag SonarProjectProperties = Tag.from("SonarProjectProperties", String.class); + public static final Tag SonarProjectName = Tag.from("SonarProjectName", String.class); + public static final Tag SonarProjectKey = Tag.from("SonarProjectKey", String.class); /* //TODO web driver settings for login feature diff --git a/testar/src/org/testar/monkey/DefaultProtocol.java b/testar/src/org/testar/monkey/DefaultProtocol.java index 16451b576..90baddead 100644 --- a/testar/src/org/testar/monkey/DefaultProtocol.java +++ b/testar/src/org/testar/monkey/DefaultProtocol.java @@ -40,7 +40,7 @@ import static org.testar.monkey.alayer.Tags.OracleVerdict; import static org.testar.monkey.alayer.Tags.SystemState; -import java.awt.Desktop; +import java.awt.*; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; @@ -52,17 +52,22 @@ import java.io.ObjectOutputStream; import java.io.PrintStream; import java.util.*; +import java.util.List; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; -import javax.swing.JFrame; -import javax.swing.JOptionPane; +import org.fruit.monkey.ProtocolDelegate; import org.testar.*; +import org.testar.monkey.alayer.Canvas; +import org.testar.monkey.alayer.Color; +import org.testar.monkey.alayer.Shape; import org.testar.reporting.Reporting; import org.testar.statemodel.StateModelManager; import org.testar.statemodel.StateModelManagerFactory; +import javafx.application.Platform; +import javafx.scene.control.Alert; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.testar.monkey.alayer.*; @@ -176,6 +181,15 @@ protected final double timeElapsed() { // Creating a logger with log4j library: private static Logger logger = LogManager.getLogger(); + protected ProtocolDelegate delegate; + + public ProtocolDelegate getDelegate() { + return delegate; + } + + public void setDelegate(ProtocolDelegate delegate) { + this.delegate = delegate; + } /** * This is the abstract flow of TESTAR (generate mode): @@ -215,19 +229,17 @@ public final void run(final Settings settings) { //initialize TESTAR with the given settings: logger.trace("TESTAR initializing with the given protocol settings"); initialize(settings); - - try { - + if (delegate != null) try { if (mode() == Modes.View) { if(isHtmlFile() || isLogFile()) { try { File file = new File(settings.get(ConfigTags.PathToReplaySequence)).getCanonicalFile(); Desktop.getDesktop().browse(file.toURI()); } catch (IOException e) { - popupMessage("Exception: Check the path of the file, something is wrong"); + delegate.popupMessage("Exception: Check the path of the file, something is wrong"); System.out.println("Exception: Check the path of the file, something is wrong"); } catch (NoSuchTagException e) { - popupMessage("Exception: ConfigTags.PathToReplaySequence is missing"); + delegate.popupMessage("Exception: ConfigTags.PathToReplaySequence is missing"); System.out.println("Exception: ConfigTags.PathToReplaySequence is missing"); } } else if (!findHTMLreport().contains("error")) { @@ -235,11 +247,11 @@ public final void run(final Settings settings) { File htmlFile = new File(findHTMLreport()); Desktop.getDesktop().browse(htmlFile.toURI()); } catch (IOException e) { - popupMessage("Exception: Select a log or html file to visualize the TESTAR results"); + delegate.popupMessage("Exception: Select a log or html file to visualize the TESTAR results"); System.out.println("Exception: Select a log or html file to visualize the TESTAR results"); } } else { - popupMessage("Please select a file.html (output/HTMLreports) to use in the View mode"); + delegate.popupMessage("Please select a file.html (output/HTMLreports) to use in the View mode"); System.out.println("Exception: Please select a file.html (output/HTMLreports) to use in the View mode"); } } else if (mode() == Modes.Replay && isValidFile()) { @@ -252,11 +264,13 @@ public final void run(final Settings settings) { runGenerateOuterLoop(system); } - }catch(WinApiException we) { - String msg = "Exception: Check whether current SUTs path: "+settings.get(ConfigTags.SUTConnectorValue) - +" is correctly defined"; + } catch(WinApiException we) { + + String msg = "Exception: Check if current SUTs path: "+settings.get(ConfigTags.SUTConnectorValue) + +" is a correct definition"; + + delegate.popupMessage(msg); - popupMessage(msg); System.out.println(msg); we.printStackTrace(); @@ -268,40 +282,55 @@ public final void run(final Settings settings) { + "Please verify your Chrome browser version: chrome://settings/help \n" + "And download the appropriate ChromeDriver version: https://chromedriver.chromium.org/downloads \n" + "\n" - //TODO check when implementing other webdriver than chromedriver - //TODO remove when automatically killing webdriver process when creating the session fails - + "As a result of this error, there is probably a \"chromedriver.exe\" process running. \n" - + "Please use Windows Task Manager to stop that process."; + //TODO check when implementing other webdriver than chromedriver + //TODO remove when automatically killing webdriver process when creating the session fails + + "As a result of this error, there is probably a \"chromedriver.exe\" process running. \n" + + "Please use Windows Task Manager to stop that process."; + + delegate.popupMessage(msg); + + System.out.println(msg); + System.out.println(e.getMessage()); + + } else { + String msg = "********** ERROR starting Selenium WebDriver ********"; + delegate.popupMessage(msg); - popupMessage(msg); System.out.println(msg); System.out.println(e.getMessage()); - }else { - System.out.println("ERROR starting Selenium WebDriver"); - e.printStackTrace(); } - }catch (IllegalStateException e) { - if (e.getMessage()!=null && e.getMessage().contains("driver executable does not exist")) { - + + } catch (IllegalStateException e) { + if (e.getMessage().contains("driver executable does not exist")) { + String msg = "Exception: Check whether chromedriver.exe path: \n" +settings.get(ConfigTags.SUTConnectorValue) +"\n exists and is correctly defined"; - popupMessage(msg); + delegate.popupMessage(msg); + System.out.println(msg); }else { e.printStackTrace(); } - }catch(SystemStartException SystemStartException) { + + } catch(SystemStartException SystemStartException) { SystemStartException.printStackTrace(); this.mode = Modes.Quit; + delegate.popupMessage(SystemStartException.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + this.mode = Modes.Quit; + delegate.popupMessage(e.getMessage()); } // can there be other kind of exceptions? + System.out.println("Protocol finished"); //allowing close-up in the end of test session: closeTestSession(); //Closing TESTAR EventHandler closeTestarTestSession(); + System.out.println("All closed"); } /** @@ -343,6 +372,7 @@ protected void initialize(Settings settings) { java.util.logging.Logger logger = java.util.logging.Logger.getLogger(GlobalScreen.class.getPackage().getName()); logger.setLevel(Level.OFF); logger.setUseParentHandlers(false); +// GlobalScreen.setEventDispatcher(new SwingDispatchService()); if (GlobalScreen.isNativeHookRegistered()) { GlobalScreen.unregisterNativeHook(); @@ -437,9 +467,13 @@ private String findHTMLreport() { * Only if GUI option is enabled (disabled for CI) */ private void popupMessage(String message) { + System.out.println("An exception occurred: " + message); if(settings.get(ConfigTags.ShowVisualSettingsDialogOnStartup)) { - JFrame frame = new JFrame(); - JOptionPane.showMessageDialog(frame, message); + Platform.runLater(() -> { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setContentText(message); + alert.showAndWait(); + }); } } @@ -479,6 +513,7 @@ private String getAndStoreGeneratedSequence() { logFileName), true))), settings.get(ConfigTags.LogLevel)); }catch (NoSuchTagException | FileNotFoundException e3) { + popupMessage("Failed to store generated sequence"); e3.printStackTrace(); } @@ -507,6 +542,7 @@ private File getAndStoreSequenceFile() { TestSerialiser.start(new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(currentSeqObject, true)))); LogSerialiser.log("Created new sequence file!\n", LogSerialiser.LogLevel.Debug); } catch (IOException e) { + popupMessage("I/O exception creating new sequence file"); LogSerialiser.log("I/O exception creating new sequence file\n", LogSerialiser.LogLevel.Critical); } @@ -573,7 +609,9 @@ private void endTestSequence(){ try { Util.delete(currentSeq); } catch (IOException e2) { - LogSerialiser.log("I/O exception deleting <" + currentSeq + ">\n", LogSerialiser.LogLevel.Critical); + final String errorMessage = "I/O exception deleting <" + currentSeq + ">"; + popupMessage(errorMessage); + LogSerialiser.log(errorMessage + "\n", LogSerialiser.LogLevel.Critical); } } @@ -605,7 +643,8 @@ private void emergencyTerminateTestSequence(SUT system, Exception e){ try { Util.delete(currentSeq); } catch (IOException e2) { - LogSerialiser.log("I/O exception deleting <" + currentSeq + ">\n", LogSerialiser.LogLevel.Critical); + final String popupMessage = "I/O exception deleting <" + currentSeq + ">"; + LogSerialiser.log(popupMessage + "a\n", LogSerialiser.LogLevel.Critical); } } @@ -707,7 +746,7 @@ protected void runGenerateOuterLoop(SUT system) { String message = "Thread: name=" + Thread.currentThread().getName() + ",id=" + Thread.currentThread().getId() + ", TESTAR throws exception"; System.out.println(message); StringJoiner stackTrace = new StringJoiner(System.lineSeparator()); - stackTrace.add(message); +// stackTrace.add(message); Arrays.stream(e.getStackTrace()).map(StackTraceElement::toString).forEach(stackTrace::add); stateModelManager.notifyTestSequenceInterruptedBySystem(stackTrace.toString()); exceptionThrown = true; @@ -716,6 +755,7 @@ protected void runGenerateOuterLoop(SUT system) { } } + if (mode() == Modes.Quit && !exceptionThrown) { // the user initiated the shutdown stateModelManager.notifyTestSequenceInterruptedByUser(); @@ -1763,7 +1803,9 @@ protected void stopSystem(SUT system) { ac.releaseCachedAutomationElements(); } if(system !=null){ + System.out.println("System class: " + system.getClass().getSimpleName()); system.stop(); + SystemProcessHandling.killRunningProcesses(system, 0); } } diff --git a/testar/src/org/testar/monkey/Main.java b/testar/src/org/testar/monkey/Main.java index 2f8ebb103..3a8f4ad32 100644 --- a/testar/src/org/testar/monkey/Main.java +++ b/testar/src/org/testar/monkey/Main.java @@ -30,6 +30,8 @@ package org.testar.monkey; +import javafx.application.Platform; +import org.fruit.monkey.ProtocolDelegate; import org.testar.CodingManager; import org.testar.StateManagementTags; import org.testar.serialisation.LogSerialiser; @@ -37,10 +39,22 @@ import org.testar.serialisation.TestSerialiser; import org.testar.monkey.alayer.Tag; -import javax.swing.*; +import javafx.application.Application; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.ChoiceDialog; +import javafx.stage.Stage; +import nl.ou.testar.jfx.MainController; +import nl.ou.testar.jfx.core.NavigationController; +import nl.ou.testar.jfx.core.NavigationDelegate; +import nl.ou.testar.jfx.core.ViewController; +import nl.ou.testar.jfx.dashboard.DashboardDelegate; + import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.util.*; @@ -51,12 +65,11 @@ import org.testar.plugin.OperatingSystems; import org.testar.extendedsettings.ExtendedSettingFile; import org.testar.extendedsettings.ExtendedSettingsFactory; -import org.testar.settingsdialog.SettingsDialog; import static org.testar.monkey.Util.compileProtocol; import static org.testar.monkey.ConfigTags.*; -public class Main { +public class Main extends Application implements DashboardDelegate, ProtocolDelegate { //public static final String TESTAR_DIR_PROPERTY = "DIRNAME"; //Use the OS environment to obtain TESTAR directory public static final String SETTINGS_FILE = "test.settings"; @@ -69,6 +82,7 @@ public class Main { public static String outputDir = testarDir + "output" + File.separator; public static String tempDir = outputDir + "temp" + File.separator; + private Stage primaryStage; /** * This method scans the settings directory of TESTAR for a file that end with extension SUT_SETTINGS_EXT @@ -86,7 +100,7 @@ public boolean accept(File dir, String name) { /** * According to the TESTAR directory and SSE file (settings and protocol to run) * return the path of the selected settings - * + * * @return test.settings path */ public static String getTestSettingsFile() { @@ -95,77 +109,102 @@ public static String getTestSettingsFile() { /** * Main method to run TESTAR - * + * * @param args * @throws IOException */ - public static void main(String[] args) throws IOException { + public static void main(String[] args) { + launch(); + } + + @Override + public void start(Stage primaryStage) throws Exception { + this.primaryStage = primaryStage; + Runtime.getRuntime().addShutdownHook(new Thread() { + + @Override + public void run() { + shutdown(); + } + }); + + System.out.println("(0)"); isValidJavaEnvironment(); - + + System.out.println("(1)"); verifyTestarInitialDirectory(); - initTestarSSE(args); + System.out.println("(2)"); + initTestarSSE(getParameters(), null); + System.out.println("(3)"); String testSettingsFileName = getTestSettingsFile(); System.out.println("Test settings is <" + testSettingsFileName + ">"); - Settings settings = loadTestarSettings(args, testSettingsFileName); + Settings settings = loadTestarSettings(getParameters().getRaw(), testSettingsFileName); // Continuous Integration: If GUI is disabled TESTAR was executed from command line. // We only want to execute TESTAR one time with the selected settings. if(!settings.get(ConfigTags.ShowVisualSettingsDialogOnStartup)){ - + System.out.println("<<< 0 >>>"); setTestarDirectory(settings); - + System.out.println("<<< 1 >>>"); initCodingManager(settings); - + System.out.println("<<< 2 >>>"); initOperatingSystem(); - + System.out.println("<<< 3 >>>"); startTestar(settings); + System.out.println("<<< 4 >>>"); + System.out.println("<<< 5 >>>"); } //TESTAR GUI is enabled, we're going to show again the GUI when the selected protocol execution finishes - else{ - while(startTestarDialog(settings, testSettingsFileName)) { - - testSettingsFileName = getTestSettingsFile(); - settings = loadTestarSettings(args, testSettingsFileName); - - setTestarDirectory(settings); - - initCodingManager(settings); + else { + System.out.println("(9)"); + startTestarDialog(primaryStage, settings, testSettingsFileName); + } + } - initOperatingSystem(); + @Override + public void stop() throws Exception { + super.stop(); + System.exit(0); + } - startTestar(settings); - } - } + @Override + public void startTesting(Settings settings) { + setTestarDirectory(settings); + initCodingManager(settings); + initOperatingSystem(); + startTestar(settings); + } + private static void shutdown() { TestSerialiser.exit(); ScreenshotSerialiser.exit(); LogSerialiser.exit(); - - System.exit(0); - } - private static boolean isValidJavaEnvironment() { + private boolean isValidJavaEnvironment() { try { if(!System.getenv("JAVA_HOME").contains("jdk")) System.out.println("JAVA HOME is not properly aiming to the Java Development Kit"); - System.out.println("Detected Java version is : " + System.getenv("JAVA_HOME")); - }catch(Exception e) { //TODO check what kind of exceptions are possible - System.out.println("Exception: Something is wrong with your JAVA_HOME \n" - +"Check if JAVA_HOME system variable is correctly defined \n \n" - +"GO TO: https://testar.org/faq/ to obtain more details \n \n"); + if(!(System.getenv("JAVA_HOME").contains("1.8") || (System.getenv("JAVA_HOME").contains("-8")))) + System.out.println("Java version is not JDK 1.8, please install "); + }catch(Exception e) { + final String errorMessage = "Exception: Something is wrong with your JAVA_HOME \n" + +"Check if JAVA_HOME system variable is correctly defined \n \n" + +"GO TO: https://testar.org/faq/ to obtain more details \n \n"; + System.out.println(errorMessage); + popupMessage(errorMessage); } return true; } - + /** * Verify the initial directory of TESTAR * If this directory didn't contain testar.bat file inform the user @@ -206,10 +245,10 @@ private static void setTestarDirectory(Settings settings) { /** * Find or create the .sse file, to known with what settings and protocol start TESTAR - * - * @param args + * + * @param parameters */ - private static void initTestarSSE(String[] args){ + private void initTestarSSE(Parameters parameters, List rawParameters){ Locale.setDefault(Locale.ENGLISH); @@ -218,11 +257,19 @@ private static void initTestarSSE(String[] args){ // and that there is exactly one. //Allow users to use command line to choose a protocol modifying sse file - for(String sett : args) { + System.out.println("[0]"); + if (rawParameters == null) { + rawParameters = parameters.getRaw(); + } + for(String sett : rawParameters) { if(sett.toString().contains("sse=")) try { protocolFromCmd(sett); - }catch(IOException e) {System.out.println("Error trying to modify sse from command line");} + }catch(Exception e) { + final String errorMessage = "Error trying to modify sse from command line"; + System.out.println(errorMessage); + popupMessage(errorMessage); + } } String[] files = getSSE(); @@ -252,7 +299,7 @@ private static void initTestarSSE(String[] args){ /** * This method creates the dropdown menu to select a protocol when TESTAR starts WITHOUT a .sse file */ - private static void settingsSelection() { + private void settingsSelection() { Set sutSettings = new HashSet(); for (File f : new File(settingsDir).listFiles()) { @@ -268,26 +315,30 @@ private static void settingsSelection() { else { Object[] options = sutSettings.toArray(); Arrays.sort(options); - JFrame settingsSelectorDialog = new JFrame(); - settingsSelectorDialog.setAlwaysOnTop(true); - String sseSelected = (String) JOptionPane.showInputDialog(settingsSelectorDialog, - "Select the desired setting:", "TESTAR settings", JOptionPane.QUESTION_MESSAGE, null, options, options[0]); - if (sseSelected == null) { + ChoiceDialog settingsSelectorDialog = new ChoiceDialog(options[0], options); + settingsSelectorDialog.setTitle("TESTAR settings"); + settingsSelectorDialog.setHeaderText("Welcome to TESTAR!"); + settingsSelectorDialog.setContentText("Select the desired setting:"); + Optional sseSelected = settingsSelectorDialog.showAndWait(); + + if (!sseSelected.isPresent()) { SSE_ACTIVATED = null; return; } - final String sseFile = sseSelected + SUT_SETTINGS_EXT; + final String sseFile = sseSelected.get() + SUT_SETTINGS_EXT; try { File f = new File(settingsDir + File.separator + sseFile); if (f.createNewFile()) { - SSE_ACTIVATED = sseSelected; + SSE_ACTIVATED = sseSelected.get(); return; } } catch (IOException e) { - System.out.println("Exception creating <" + sseFile + "> file"); + final String errorMessage = "Exception creating <" + sseFile + "> file"; + System.out.println(errorMessage); + popupMessage(errorMessage); } } @@ -297,12 +348,12 @@ private static void settingsSelection() { //TODO: After know what overrideWithUserProperties does, unify this method with loadSettings /** * Load the settings of the selected test.settings file - * + * * @param args * @param testSettingsFileName * @return settings */ - private static Settings loadTestarSettings(String[] args, String testSettingsFileName){ + private Settings loadTestarSettings(List args, String testSettingsFileName){ Settings settings = null; try { @@ -313,7 +364,7 @@ private static Settings loadTestarSettings(String[] args, String testSettingsFil //TODO: Understand what this exactly does? overrideWithUserProperties(settings); - Float SST = settings.get(ConfigTags.StateScreenshotSimilarityThreshold, null); + Float SST = null;//settings.get(ConfigTags.StateScreenshotSimilarityThreshold, null); if (SST != null) { System.setProperty("SCRSHOT_SIMILARITY_THRESHOLD", SST.toString()); } @@ -323,32 +374,40 @@ private static Settings loadTestarSettings(String[] args, String testSettingsFil /** * Open TESTAR GUI to allow the users modify the settings and the protocol with which the want run TESTAR - * + * * @param settings * @param testSettingsFileName * @return true if users starts TESTAR, or false is users close TESTAR */ - public static boolean startTestarDialog(Settings settings, String testSettingsFileName) { - // Start up the TESTAR Dialog - try { - if ((settings = new SettingsDialog().run(settings, testSettingsFileName)) == null) { - return false; + public void startTestarDialog(Stage stage, Settings settings, String testSettingsFileName) { + System.out.println("Starting TESTARne4dfx dialog"); + final String settingsPath = getTestSettingsFile(); + + MainController mainController = new MainController(settings, settingsPath); + mainController.getDashboardController().setDelegate(this); + NavigationController navigationController = new NavigationController(mainController); + navigationController.startWithDelegate(new NavigationDelegate() { + @Override + public void onViewControllerActivated(ViewController viewController, Parent view) { + stage.setTitle(viewController.getTitle()); + stage.setScene(new Scene(view)); + stage.sizeToScene(); + stage.show(); } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return true; + }); } /** * Start TESTAR protocol with the selected settings - * + * + * * This method get the specific protocol class of the selected settings to run TESTAR - * + * * @param settings */ - private static void startTestar(Settings settings) { + private void startTestar(Settings settings) { + +// launch(); // Compile the Java protocols if AlwaysCompile setting is true if (settings.get(ConfigTags.AlwaysCompile)) { @@ -381,40 +440,81 @@ private static void startTestar(Settings settings) { LogSerialiser.log("Starting TESTAR protocol ...\n", LogSerialiser.LogLevel.Debug); + if (DefaultProtocol.class.isInstance(protocol)) { + ((DefaultProtocol)protocol).setDelegate(this); + } + //Run TESTAR protocol with the selected settings protocol.run(settings); } catch (InstantiationException e) { - e.printStackTrace(); - e.printStackTrace(LogSerialiser.getLogStream()); LogSerialiser.log("An unexpected error occurred: " + e + "\n", LogSerialiser.LogLevel.Critical); - } catch (InvocationTargetException e) { + System.err.println("An unexpected error occurred: " + e.getMessage() + "\n"); + System.out.println("Main: Exception caught"); + popupMessage(e.getMessage()); e.printStackTrace(); - e.printStackTrace(LogSerialiser.getLogStream()); + final PrintStream logStream = LogSerialiser.getLogStream(); + if (logStream != null) { + e.printStackTrace(LogSerialiser.getLogStream()); + } + } catch (InvocationTargetException e) { LogSerialiser.log("An unexpected error occurred: " + e + "\n", LogSerialiser.LogLevel.Critical); - } catch (NoSuchMethodException e) { + System.err.println("An unexpected error occurred: " + e.getMessage() + "\n"); + System.out.println("Main: Exception caught"); + popupMessage(e.getMessage()); e.printStackTrace(); - e.printStackTrace(LogSerialiser.getLogStream()); + final PrintStream logStream = LogSerialiser.getLogStream(); + if (logStream != null) { + e.printStackTrace(LogSerialiser.getLogStream()); + } + } catch (NoSuchMethodException e) { LogSerialiser.log("An unexpected error occurred: " + e + "\n", LogSerialiser.LogLevel.Critical); - } catch (MalformedURLException e) { + System.err.println("An unexpected error occurred: " + e.getMessage() + "\n"); + System.out.println("Main: Exception caught"); + popupMessage(e.getMessage()); e.printStackTrace(); - e.printStackTrace(LogSerialiser.getLogStream()); + final PrintStream logStream = LogSerialiser.getLogStream(); + if (logStream != null) { + e.printStackTrace(LogSerialiser.getLogStream()); + } + } catch (MalformedURLException e) { LogSerialiser.log("An unexpected error occurred: " + e + "\n", LogSerialiser.LogLevel.Critical); - } catch (IllegalAccessException e) { + System.err.println("An unexpected error occurred: " + e.getMessage() + "\n"); + System.out.println("Main: Exception caught"); + popupMessage(e.getMessage()); e.printStackTrace(); - e.printStackTrace(LogSerialiser.getLogStream()); + final PrintStream logStream = LogSerialiser.getLogStream(); + if (logStream != null) { + e.printStackTrace(LogSerialiser.getLogStream()); + } + } catch (IllegalAccessException e) { LogSerialiser.log("An unexpected error occurred: " + e + "\n", LogSerialiser.LogLevel.Critical); - } catch (ClassNotFoundException e) { + System.err.println("An unexpected error occurred: " + e.getMessage() + "\n"); + System.out.println("Main: Exception caught"); + popupMessage(e.getMessage()); e.printStackTrace(); - e.printStackTrace(LogSerialiser.getLogStream()); + final PrintStream logStream = LogSerialiser.getLogStream(); + if (logStream != null) { + e.printStackTrace(LogSerialiser.getLogStream()); + } + } catch (ClassNotFoundException e) { LogSerialiser.log("An unexpected error occurred: " + e + "\n", LogSerialiser.LogLevel.Critical); - } finally { - // Closing TESTAR + System.err.println("An unexpected error occurred: " + e.getMessage() + "\n"); + System.out.println("Main: Exception caught"); + popupMessage(e.getMessage()); + e.printStackTrace(); + final PrintStream logStream = LogSerialiser.getLogStream(); + if (logStream != null) { + e.printStackTrace(LogSerialiser.getLogStream()); + } + } + finally { if (loader != null) { try { loader.close(); } catch (IOException e) { e.printStackTrace(); + popupMessage(e.getMessage()); } } @@ -428,12 +528,12 @@ private static void startTestar(Settings settings) { /** * Load the default settings for all the configurable settings and add/overwrite with those from the file * This is needed because the user might not have set all the possible settings in the test.settings file. - * @param argv + * @param args * @param file * @return An instance of Settings * @throws ConfigException */ - public static Settings loadSettings(String[] argv, String file) throws ConfigException { + public Settings loadSettings(List args, String file) throws ConfigException { Assert.notNull(file); try { List> defaults = new ArrayList>(); @@ -583,13 +683,19 @@ public static Settings loadSettings(String[] argv, String file) throws ConfigExc Settings settings = Settings.fromFile(defaults, file); //If user use command line to input properties, mix file settings with cmd properties - if(argv.length>0) { + + int size = args.size(); + if(size>0) { + String argArray[] = new String[size]; try { - settings = Settings.fromFileCmd(defaults, file, argv); - }catch(IOException e) { - System.out.println("Error with command line properties. Examples:"); - System.out.println("testar SUTConnectorValue=\"C:\\\\Windows\\\\System32\\\\notepad.exe\" Sequences=11 SequenceLength=12 SuspiciousTitle=.*aaa.*"); - System.out.println("SUTConnectorValue=\" \"\"C:\\\\Program Files\\\\Internet Explorer\\\\iexplore.exe\"\" \"\"https://www.google.es\"\" \""); + settings = Settings.fromFileCmd(defaults, file, args.toArray(argArray)); + }catch(Exception e) { + final String errorMessage = "Error with command line properties. Examples:\n" + + "testar SUTConnectorValue=\"C:\\\\Windows\\\\System32\\\\notepad.exe\" Sequences=11 SequenceLength=12 SuspiciousTitle=.*aaa.*\n" + + "SUTConnectorValue=\" \"\"C:\\\\Program Files\\\\Internet Explorer\\\\iexplore.exe\"\" \"\"https://www.google.es\"\" \""; + + System.out.println(errorMessage); + popupMessage(errorMessage); } //SUTConnectorValue=" ""C:\\Program Files\\Internet Explorer\\iexplore.exe"" ""https://www.google.es"" " //SUTConnectorValue="C:\\Windows\\System32\\notepad.exe" @@ -616,7 +722,7 @@ public static Settings loadSettings(String[] argv, String file) throws ConfigExc /** * This method creates a sse file to change TESTAR protocol if sett param matches an existing protocol * @param sett - * @throws IOException + * @throws IOException */ public static void protocolFromCmd(String sett) throws IOException { String sseName = sett.substring(sett.indexOf("=")+1); @@ -637,7 +743,7 @@ public static void protocolFromCmd(String sett) throws IOException { //Obtain previous sse file and delete it (if exist) String[] files = getSSE(); if (files != null) { - for (String f : files) + for (String f : files) new File(settingsDir+f).delete(); } @@ -781,4 +887,28 @@ private static void initOperatingSystem() { Environment.setInstance(new UnknownEnvironment()); } } + + /** + * Shows the error message dialog + * + * @param message + */ + public void popupMessage(String message) { + Platform.runLater(() -> { + final Alert alert = new Alert(Alert.AlertType.ERROR, + (message == null || message.length() == 0 ? "Unknown error" : message)); + alert.show(); + }); + } + + /** + * Opens link in a browser + * + * @param uri + */ + public void openURI(URI uri) { + Platform.runLater(() -> { + getHostServices().showDocument(uri.toString()); + }); + } } diff --git a/testar/src/org/testar/monkey/RuntimeControlsProtocol.java b/testar/src/org/testar/monkey/RuntimeControlsProtocol.java index bbc3972ac..0c8a2a60c 100644 --- a/testar/src/org/testar/monkey/RuntimeControlsProtocol.java +++ b/testar/src/org/testar/monkey/RuntimeControlsProtocol.java @@ -34,9 +34,10 @@ import org.testar.EventHandler; import org.testar.FlashFeedback; import org.testar.IEventListener; +import org.testar.monkey.alayer.devices.MouseButtons; import org.testar.serialisation.LogSerialiser; import org.testar.monkey.alayer.devices.KBKeys; -import org.testar.monkey.alayer.devices.MouseButtons; + import java.util.EnumSet; import java.util.Set; @@ -71,7 +72,6 @@ public EventHandler initializeEventHandler() { /** * Implement the SHIFT + ARROW-LEFT or SHIFT + ARROW-RIGHT toggling mode feature * Show the flashfeedback in the upperleft corner of the screen - * @param forward is set in keyDown method */ private synchronized void nextMode() { switch(mode){ @@ -92,7 +92,7 @@ private synchronized void nextMode() { String modeNfo = "'" + mode + "' mode active." + modeParamS; LogSerialiser.log(modeNfo + "\n", LogSerialiser.LogLevel.Info); if (settings.get(ConfigTags.FlashFeedback)) { - FlashFeedback.flash(modeNfo, 1000); +// FlashFeedback.flash(modeNfo, 1000); } } diff --git a/testar/src/org/testar/monkey/WindowsCommandLineSutConnector.java b/testar/src/org/testar/monkey/WindowsCommandLineSutConnector.java index 2be6eae08..5be2e1ee1 100644 --- a/testar/src/org/testar/monkey/WindowsCommandLineSutConnector.java +++ b/testar/src/org/testar/monkey/WindowsCommandLineSutConnector.java @@ -74,7 +74,7 @@ public SUT startOrConnectSut() { if (flashFeedback) { int countTimeFlash = 0; while(countTimeFlash ms ... waiting UI to be accessible"); state = builder.apply(sut); @@ -107,7 +107,7 @@ public SUT startOrConnectSut() { //Print info to the user to know that TESTAR is NOT READY for its use :-( if (flashFeedback) { printSutInfo = "Waiting for the SUT to be accessible ..."; - FlashFeedback.flash(printSutInfo, 500); +// FlashFeedback.flash(printSutInfo, 500); } } Util.pauseMs(500); diff --git a/testar/src/org/testar/plugin/UnsupportedPlatformException.java b/testar/src/org/testar/plugin/UnsupportedPlatformException.java index 5c42d7942..d9037ea98 100644 --- a/testar/src/org/testar/plugin/UnsupportedPlatformException.java +++ b/testar/src/org/testar/plugin/UnsupportedPlatformException.java @@ -35,7 +35,7 @@ public class UnsupportedPlatformException extends RuntimeException { private static final long serialVersionUID = -763558210570361617L; public UnsupportedPlatformException() { - super(); + super("Platform not supported"); } public UnsupportedPlatformException(String message) { diff --git a/testar/src/org/testar/protocols/WebdriverProtocol.java b/testar/src/org/testar/protocols/WebdriverProtocol.java index 4a0217491..38dadbed8 100644 --- a/testar/src/org/testar/protocols/WebdriverProtocol.java +++ b/testar/src/org/testar/protocols/WebdriverProtocol.java @@ -283,6 +283,7 @@ protected State getState(SUT system) throws StateBuildException { try { WdDriver.waitDocumentReady(); } catch(org.openqa.selenium.WebDriverException wde) { + delegate.popupMessage("WEBDRIVER ERROR: Selenium Chromedriver seems not to respond!"); LogSerialiser.log("WEBDRIVER ERROR: Selenium Chromedriver seems not to respond!\n", LogSerialiser.LogLevel.Critical); System.out.println("******************************************************************"); System.out.println("** WEBDRIVER ERROR: Selenium Chromedriver seems not to respond! **"); @@ -772,9 +773,10 @@ protected void ensureDomainsAllowed() { domainsAllowed = Arrays.asList(ArrayUtils.insert(newDomainsAllowed.length, newDomainsAllowed, getDomain(initialUrl))); System.out.println(String.format("domainsAllowed: %s", String.join(",", domainsAllowed))); } - } catch(Exception e) { //TODO check what kind of exception can happen - System.out.println("WEBDRIVER ERROR: Trying to add the startup domain to domainsAllowed List"); - System.out.println("Please review domainsAllowed List inside Webdriver Java Protocol"); + } catch(Exception e) { + final String errorMessage = "WEBDRIVER ERROR: Trying to add the startup domain to domainsAllowed List\nPlease review domainsAllowed List inside Webdriver Java Protocol"; + delegate.popupMessage(errorMessage); + System.out.println(errorMessage); } } diff --git a/testar/src/org/testar/settingsdialog/ProtocolEditor.java b/testar/src/org/testar/settingsdialog/ProtocolEditor.java deleted file mode 100644 index 63d5fe5de..000000000 --- a/testar/src/org/testar/settingsdialog/ProtocolEditor.java +++ /dev/null @@ -1,203 +0,0 @@ -/*************************************************************************************************** -* -* Copyright (c) 2013, 2014, 2015, 2016, 2017 Universitat Politecnica de Valencia - www.upv.es -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************************************/ - - -/** - * @author Sebastian Bauersfeld - */ -package org.testar.settingsdialog; - -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - -import jsyntaxpane.DefaultSyntaxKit; -import org.testar.monkey.Util; - -public class ProtocolEditor extends javax.swing.JDialog { - private static final long serialVersionUID = 5922037291232012481L; - - private String settingsDir; - private String protocolClass; // by urueda - - //public ProtocolEditor() { - public ProtocolEditor(String settingsDir, String protocolClass) { // by urueda - this.settingsDir = settingsDir; - this.protocolClass = protocolClass; - DefaultSyntaxKit.initKit(); - initComponents(); - codeEditor.setContentType("text/java"); - //codeEditor.setText(Util.readFile(new File("./CustomProtocol.java"))); - codeEditor.setText(Util.readFile(getProtocolFile())); - } - - private void initComponents() { - jScrollPane1 = new javax.swing.JScrollPane(); - codeEditor = new javax.swing.JEditorPane(); - btnCompile = new javax.swing.JButton(); - jScrollPane2 = new javax.swing.JScrollPane(); - console = new javax.swing.JTextArea(); - - // by mimarmu1 - setTitle("Protocol editor"); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - setMinimumSize(new java.awt.Dimension(800, 400)); - addWindowListener(new java.awt.event.WindowAdapter() { - public void windowClosed(java.awt.event.WindowEvent evt) { - formWindowClosed(evt); - } - }); - - codeEditor.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyPressed(java.awt.event.KeyEvent evt) { - codeEditorKeyPressed(evt); - } - }); - jScrollPane1.setViewportView(codeEditor); - jScrollPane1.getVerticalScrollBar().setUnitIncrement(5); - - - btnCompile.setText("Save and Compile"); - btnCompile.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCompileActionPerformed(evt); - } - }); - btnCompile.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyPressed(java.awt.event.KeyEvent evt) { - btnCompileKeyPressed(evt); - } - }); - - console.setColumns(20); - console.setLineWrap(true); - console.setRows(5); - console.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyPressed(java.awt.event.KeyEvent evt) { - consoleKeyPressed(evt); - } - }); - jScrollPane2.setViewportView(console); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1) - .addComponent(jScrollPane2) - .addComponent(btnCompile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 570, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnCompile) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 122, javax.swing.GroupLayout.PREFERRED_SIZE)) - ); - - pack(); - } - - - private void compile() { - try { - console.setText("Compiling..."); - console.update(console.getGraphics()); - //Util.saveToFile(codeEditor.getText(), "./CustomProtocol.java"); - // begin by urueda - File protocolFile = getProtocolFile(); - Util.saveToFile(codeEditor.getText(), protocolFile.getPath()); - File compileDir = protocolFile.getParentFile(); - List fileList = new ArrayList(1); fileList.add(compileDir); // by urueda - Util.compileJava(settingsDir, fileList, - System.getProperty("java.class.path")); //";./monkey.jar"); - // end bu urueda - console.setText(console.getText() + "OK"); - } catch (IOException t) { - console.setText(console.getText() + "\n" + t.getMessage()); - } - } - - private File getProtocolFile() { - File protocolFile ; - if (Paths.get(protocolClass).isAbsolute()) { - protocolFile = new File(protocolClass + ".java"); - } - else { - protocolFile = new File(settingsDir + protocolClass + ".java"); - } - return protocolFile; - } - - private void btnCompileActionPerformed(java.awt.event.ActionEvent evt) { - compile(); - } - - private void codeEditorKeyPressed(java.awt.event.KeyEvent evt) { - if ((evt.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) { - if (evt.getKeyCode() == KeyEvent.VK_ENTER) { - compile(); - } - }else if(evt.getKeyCode() == KeyEvent.VK_ESCAPE){ - this.dispose(); - } - } - - private void formWindowClosed(java.awt.event.WindowEvent evt) { - try { - //Util.saveToFile(codeEditor.getText(), "./CustomProtocol.java"); - Util.saveToFile(codeEditor.getText(), getProtocolFile().getPath()); // by urueda - } catch (IOException ioe) { - System.out.println(ioe); - } - } - - private void consoleKeyPressed(java.awt.event.KeyEvent evt) { - if(evt.getKeyCode() == KeyEvent.VK_ESCAPE) - this.dispose(); - } - - private void btnCompileKeyPressed(java.awt.event.KeyEvent evt) { - if(evt.getKeyCode() == KeyEvent.VK_ESCAPE) - this.dispose(); - } - - private javax.swing.JButton btnCompile; - private javax.swing.JEditorPane codeEditor; - private javax.swing.JTextArea console; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JScrollPane jScrollPane2; -} diff --git a/testar/src/org/testar/settingsdialog/SettingsDialog.java b/testar/src/org/testar/settingsdialog/SettingsDialog.java deleted file mode 100644 index f8caeca21..000000000 --- a/testar/src/org/testar/settingsdialog/SettingsDialog.java +++ /dev/null @@ -1,417 +0,0 @@ -/*************************************************************************************************** -* -* Copyright (c) 2013 - 2021 Universitat Politecnica de Valencia - www.upv.es -* Copyright (c) 2018 - 2021 Open Universiteit - www.ou.nl -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************************************/ - - -package org.testar.settingsdialog; - -import org.testar.monkey.*; -import org.testar.serialisation.LogSerialiser; -import org.testar.settingsdialog.dialog.*; -import org.testar.settingsdialog.dialog.StateModelPanel; - -import org.testar.extendedsettings.ExtendedSettingsFactory; - -import javax.imageio.ImageIO; -import javax.swing.*; -import javax.swing.GroupLayout.Alignment; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Observable; -import java.util.Observer; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import static java.util.logging.Logger.getLogger; -import static javax.swing.GroupLayout.DEFAULT_SIZE; -import static javax.swing.GroupLayout.PREFERRED_SIZE; -import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; -import static javax.swing.UIManager.*; - - -/** - * This class takes care of the SettingsDialogue of TESTAR (the TESTAR GUI). - */ - -public class SettingsDialog extends JFrame implements Observer { - private static final long serialVersionUID = 5156320008281200950L; - - static final String TESTAR_VERSION = "2.5.0 (21-Jun-2022)"; - - private String settingsFile; - private Settings settings; - //TODO: what is this ret variable. Cant you just return settings in the run method? - private Settings ret; - - private JButton btnGenerate; - private JButton btnSpy; - private JButton btnReplay; - private JButton btnView; - private JButton btnRecord; - - private static final int GENERAL_TAB_INDEX = 1; - private final Map> settingPanels = new HashMap<>(); - - /** - * Starts the settings Dialog. - * @throws IOException when Icons cannot be found. - */ - public SettingsDialog() throws IOException { - getContentPane().setBackground(Color.WHITE); - try { - for (LookAndFeelInfo info : getInstalledLookAndFeels()) { - if ("Nimbus".equals(info.getName())) { - setLookAndFeel(info.getClassName()); - break; - } - } - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { - getLogger(SettingsDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - } - this.setIconImage(loadIcon("/icons/logos/TESTAR.jpg")); - - ToolTipManager.sharedInstance().setDismissDelay(25000); - ToolTipManager.sharedInstance().setInitialDelay(100); - initComponents(); - - this.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - saveCurrentSettings(); - } - }); - } - - /** - * - * @param settings - * @param settingsFile - * @return - */ - public Settings run(Settings settings, String settingsFile) { - this.settings = settings; - this.settingsFile = settingsFile; - this.ret = null; - populateInformation(settings); - this.setVisible(true); - - while (this.isShowing()) - Util.pause(0.1); - - return ret; - } - - public static Image loadIcon(String path) throws IOException { - return ImageIO.read(SettingsDialog.class.getResourceAsStream(path)); - } - - /** - * This is the method that is called when you click on one of the big mode buttons in TESTAR dialog - * @param mode indicates the MODE button that was clicked. - */ - private void start(RuntimeControlsProtocol.Modes mode) { - try { - extractInformation(settings); - checkSettings(settings); - settings.set(ConfigTags.Mode, mode); - saveCurrentSettings(); - ret = settings; - this.dispose(); - } catch (IllegalStateException ise) { - JOptionPane.showMessageDialog(this, ise.getMessage(), "Invalid Settings!", JOptionPane.ERROR_MESSAGE); - } - } - - private void checkSettings(Settings settings) throws IllegalStateException { - String userInputPattern = settings.get(ConfigTags.ProcessesToKillDuringTest); - try { - Pattern.compile(userInputPattern); - } catch (PatternSyntaxException exception) { - throw new IllegalStateException("Your ProcessFilter is not a valid regular expression!"); - } - - userInputPattern = settings.get(ConfigTags.ClickFilter); - try { - Pattern.compile(userInputPattern); - } catch (PatternSyntaxException exception) { - throw new IllegalStateException("Your ClickFilter is not a valid regular expression!"); - } - - userInputPattern = settings.get(ConfigTags.SuspiciousTitles); - try { - Pattern.compile(userInputPattern); - } catch (PatternSyntaxException exception) { - throw new IllegalStateException("Your Oracle is not a valid regular expression!"); - } - - if (!new File(settings.get(ConfigTags.OutputDir)).exists()) { - throw new IllegalStateException("Output Directory does not exist!"); - } - if (!new File(settings.get(ConfigTags.TempDir)).exists()) { - throw new IllegalStateException("Temp Directory does not exist!"); - } - - settingPanels.forEach((k,v) -> v.right().checkSettings()); - } - - private void saveCurrentSettings() { - extractInformation(settings); - ExtendedSettingsFactory.SaveAll(); - try { - Util.saveToFile(settings.toFileString(), settingsFile); - Settings.setSettingsPath(settingsFile.substring(0,settingsFile.indexOf(Main.SETTINGS_FILE)-1)); - System.out.println("Saved current settings to <" + settingsFile + ">"); - } catch (IOException e1) { - LogSerialiser.log("Unable to save current settings to <" + settingsFile + ">: " + e1.toString() + "\n"); - } - } - - /** - * This replaces the original test.settings file with a complete settings file - * @param sutSettings - */ - private void switchSettings(String sutSettings) { - String previousSSE = Main.getSSE()[0]; - String sse = sutSettings + Main.SUT_SETTINGS_EXT; - if (previousSSE.equals(sse)) { - return; - } - saveCurrentSettings(); - String settingsDir = Main.settingsDir; - new File(settingsDir + previousSSE).renameTo(new File(settingsDir + sse)); - try { - settingsFile = settingsDir + sutSettings + File.separator + Main.SETTINGS_FILE; - settings = Main.loadSettings(new String[0], settingsFile); - populateInformation(settings); - System.out.println("Switched to <" + settingsFile + ">"); - Main.SSE_ACTIVATED = sutSettings; - - } catch (ConfigException cfe) { - LogSerialiser.log("Unable to switch to <" + sutSettings + "> settings!\n"); - } - } - - private void populateInformation(Settings settings) { - settingPanels.forEach((k,v) -> v.right().populateFrom(settings)); - } - - private void extractInformation(Settings settings) { - settingPanels.forEach((k,v) -> v.right().extractInformation(settings)); - } - - private void initComponents() throws IOException { - // Init start buttons - btnGenerate = getBtnGenerate(); - btnSpy = getBtnSpy(); - btnReplay = getBtnReplay(); - btnView = getBtnView(); - btnRecord = getBtnRecord(); - - JTabbedPane jTabsPane = new JTabbedPane(); - jTabsPane.addTab("About", new AboutPanel()); - settingPanels.put(GENERAL_TAB_INDEX, new Pair<>("General Settings", new GeneralPanel(this))); - settingPanels.put(settingPanels.size() + 1, new Pair<>("Filters", new FilterPanel())); - settingPanels.put(settingPanels.size() + 1, new Pair<>("Oracles", new OraclePanel())); - settingPanels.put(settingPanels.size() + 1, new Pair<>("Time Settings", new TimingPanel())); - settingPanels.put(settingPanels.size() + 1, new Pair<>("Misc", new MiscPanel())); - settingPanels.put(settingPanels.size() + 1, new Pair<>("VCS Options", new VCSPanel())); - settingPanels.put(settingPanels.size() + 1, new Pair<>("State Model", StateModelPanel.createStateModelPanel())); - - settingPanels.forEach((k,v) -> jTabsPane.add(v.left(),v.right())); - - setLayout(jTabsPane); - pack(); - setCentreScreen(); - } - - /** - * Make the window appear centre screen - */ - private void setCentreScreen() { - Dimension scrDim = Toolkit.getDefaultToolkit().getScreenSize(); - - Rectangle bounds = new Rectangle(); - bounds.x = (int) scrDim.getWidth() / 2 - getWidth() / 2; - bounds.y = (int) scrDim.getHeight() / 2 - getHeight() / 2; - bounds.width = getWidth(); - bounds.height = getHeight(); - - setBounds(bounds); - } - - private void setLayout(JTabbedPane jTabsPane) { - jTabsPane.setSelectedIndex(GENERAL_TAB_INDEX); - - setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - setTitle("TESTAR " + TESTAR_VERSION); - setLocationByPlatform(true); - setName("TESTAR Settings"); // NOI18N - setResizable(false); - - GroupLayout layout = new GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - - layout.setHorizontalGroup( - layout.createParallelGroup(Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(Alignment.TRAILING) - .addComponent(jTabsPane, PREFERRED_SIZE, 620, PREFERRED_SIZE) - .addGroup(getStartGroup(layout))) - .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(Alignment.LEADING) - .addComponent(btnGenerate, PREFERRED_SIZE, 129, PREFERRED_SIZE) - .addComponent(btnSpy, PREFERRED_SIZE, 129, PREFERRED_SIZE) - .addComponent(btnReplay, PREFERRED_SIZE, 129, PREFERRED_SIZE) - .addComponent(btnView, PREFERRED_SIZE, 129, PREFERRED_SIZE) - .addComponent(btnRecord, PREFERRED_SIZE, 129, PREFERRED_SIZE) - ) - .addPreferredGap(RELATED) - .addComponent(jTabsPane, PREFERRED_SIZE, 400, PREFERRED_SIZE) - .addContainerGap()) - ); - } - - private GroupLayout.SequentialGroup getStartGroup(GroupLayout layout) { - GroupLayout.SequentialGroup group = layout.createSequentialGroup(); - - group.addComponent(btnSpy, 120, 120, 120); - group.addGap(2, 2, 2); - group.addComponent(btnGenerate, 120, 120, 120); - group.addGap(2, 2, 2); - group.addComponent(btnRecord, 120, 120, 120); - group.addGap(2, 2, 2); - group.addComponent(btnReplay, 120, 120, 120); - group.addGap(2, 2, 2); - group.addComponent(btnView, 120, 120, 120); - - return group; - } - - private JButton getBtnGenerate() throws IOException { - JButton btn = new JButton(); - btn.setBackground(new Color(255, 255, 255)); - btn.setIcon(new ImageIcon(loadIcon("/icons/button_generate.png"))); - btn.setToolTipText(ToolTipTexts.btnGenerateTTT); - btn.setFocusPainted(false); - btn.addActionListener(this::btnGenerateActionPerformed); - return btn; - } - - private void btnGenerateActionPerformed(ActionEvent evt) { - start(RuntimeControlsProtocol.Modes.Generate); - } - - private JButton getBtnSpy() throws IOException { - JButton btn = new JButton(); - btn.setBackground(new Color(255, 255, 255)); - btn.setIcon(new ImageIcon(loadIcon("/icons/button_spy.png"))); - btn.setToolTipText(ToolTipTexts.btnSpyTTT); - btn.setFocusPainted(false); - btn.addActionListener(this::btnSpyActionPerformed); - return btn; - } - - private void btnSpyActionPerformed(ActionEvent evt) { - start(RuntimeControlsProtocol.Modes.Spy); - } - - private JButton getBtnReplay() throws IOException { - JButton btn = new JButton(); - btn.setBackground(new Color(255, 255, 255)); - btn.setIcon(new ImageIcon(loadIcon("/icons/button_replay.png"))); - btn.setToolTipText(ToolTipTexts.btnReplayTTT); - btn.setFocusPainted(false); - btn.addActionListener(this::btnReplayActionPerformed); - return btn; - } - - private void btnReplayActionPerformed(ActionEvent evt) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.FILES_ONLY); - fd.setCurrentDirectory(new File(settings.get(ConfigTags.PathToReplaySequence)).getParentFile()); - - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - settings.set(ConfigTags.PathToReplaySequence, file); - start(RuntimeControlsProtocol.Modes.Replay); - } - } - - private JButton getBtnView() throws IOException { - JButton btn = new JButton(); - btn.setBackground(new Color(255, 255, 255)); - btn.setIcon(new ImageIcon(loadIcon("/icons/button_view.png"))); - btn.setToolTipText(ToolTipTexts.btnViewTTT); - btn.setFocusPainted(false); - btn.addActionListener(this::btnViewActionPerformed); - return btn; - } - - private void btnViewActionPerformed(ActionEvent evt) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.FILES_ONLY); - fd.setCurrentDirectory(new File(settings.get(ConfigTags.PathToReplaySequence)).getParentFile()); - - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - settings.set(ConfigTags.PathToReplaySequence, file); - start(RuntimeControlsProtocol.Modes.View); - } - } - - private JButton getBtnRecord() throws IOException { - JButton btn = new JButton(); - btn.setBackground(new Color(255, 255, 255)); - btn.setIcon(new ImageIcon(loadIcon("/icons/button_record.png"))); - btn.setToolTipText(ToolTipTexts.btnRecordTTT); - btn.setFocusPainted(false); - btn.addActionListener(this::btnRecordActionPerformed); - return btn; - } - - private void btnRecordActionPerformed(ActionEvent evt) { - start(RuntimeControlsProtocol.Modes.Record); - } - - @Override - public void update(Observable o, Object arg) { - switchSettings((String) arg); - } -} diff --git a/testar/src/org/testar/settingsdialog/SettingsPanel.java b/testar/src/org/testar/settingsdialog/SettingsPanel.java deleted file mode 100644 index 49c9810da..000000000 --- a/testar/src/org/testar/settingsdialog/SettingsPanel.java +++ /dev/null @@ -1,60 +0,0 @@ -/*************************************************************************************************** - * - * Copyright (c) 2020 Open Universiteit - www.ou.nl - * Copyright (c) 2020 Universitat Politecnica de Valencia - www.upv.es - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************************************/ - -package org.testar.settingsdialog; - -import org.testar.monkey.Settings; - -import javax.swing.*; - -/** - * Abstract class for all common functionality for a SettingsPanel. - */ -public abstract class SettingsPanel extends JPanel { - /** - * Populate the fields from Settings structure. - * - * @param settings The settings to load. - */ - public abstract void populateFrom(final Settings settings); - - /** - * Retrieve information from the GUI. - * - * @param settings reference to the object where the settings will be stored. - */ - public abstract void extractInformation(final Settings settings); - - /** - * Validate that the settings are valid. - */ - public void checkSettings() { - } -} diff --git a/testar/src/org/testar/settingsdialog/dialog/AboutPanel.java b/testar/src/org/testar/settingsdialog/dialog/AboutPanel.java deleted file mode 100644 index 3268220f1..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/AboutPanel.java +++ /dev/null @@ -1,110 +0,0 @@ -/*************************************************************************************************** - * - * Copyright (c) 2013, 2014, 2015, 2016, 2017, 2018, 2019 Universitat Politecnica de Valencia - www.upv.es - * Copyright (c) 2018, 2019 Open Universiteit - www.ou.nl - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************************************/ - - -package org.testar.settingsdialog.dialog; - -import org.testar.settingsdialog.SettingsDialog; - -import javax.swing.*; -import java.awt.*; -import java.io.IOException; - -import static javax.swing.GroupLayout.PREFERRED_SIZE; - -public class AboutPanel extends JPanel { - - private static final long serialVersionUID = 5542811933551996647L; - - private JLabel lblUPVLogo = getLogo("/icons/logos/upv_pros.png"); - private JLabel testarLogo = getLogo("/icons/logos/testar_logo.png"); - private JLabel ouLogo = getLogo("/icons/logos/ou.jpg"); - private JLabel testomatLogo = getLogo("/icons/logos/TESTOMAT_Logo.png"); - private JLabel fittestLogo = getLogo("/icons/logos/fittest_logo.png"); - private JLabel decoderLogo = getLogo("/icons/logos/decoder_logo.jpg"); - private JLabel ivvesLogo = getLogo("/icons/logos/ivves_logo.jpg"); - private JLabel iv4xrLogo = getLogo("/icons/logos/iv4xr_logo.png"); - - - public AboutPanel () throws IOException { - setBackground(Color.WHITE); - - GroupLayout aboutPanelLayout = new GroupLayout(this); - setLayout(aboutPanelLayout); - aboutPanelLayout.setHorizontalGroup( - aboutPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(aboutPanelLayout.createSequentialGroup() - .addGroup(aboutPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(aboutPanelLayout.createSequentialGroup() - .addGap(40) - .addComponent(ouLogo, PREFERRED_SIZE, 90, PREFERRED_SIZE) - .addGap(80) - .addComponent(testarLogo, PREFERRED_SIZE, 190, PREFERRED_SIZE) - .addGap(40) - .addComponent(lblUPVLogo, PREFERRED_SIZE, 190, PREFERRED_SIZE)) - .addGroup(aboutPanelLayout.createSequentialGroup() - .addGap(144) - .addComponent(testomatLogo, PREFERRED_SIZE, 150, PREFERRED_SIZE) - .addGap(40) - .addComponent(fittestLogo, PREFERRED_SIZE, 150, PREFERRED_SIZE)) - .addGroup(aboutPanelLayout.createSequentialGroup() - .addGap(40) - .addComponent(decoderLogo, PREFERRED_SIZE, 150, PREFERRED_SIZE) - .addGap(40) - .addComponent(iv4xrLogo, PREFERRED_SIZE, 150, PREFERRED_SIZE) - .addGap(40) - .addComponent(ivvesLogo, PREFERRED_SIZE, 150, PREFERRED_SIZE))) - .addContainerGap()) - ); - aboutPanelLayout.setVerticalGroup( - aboutPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) - .addGroup(aboutPanelLayout.createSequentialGroup() - .addGap(10) - .addGroup(aboutPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) - .addComponent(lblUPVLogo, PREFERRED_SIZE, 110, PREFERRED_SIZE) - .addComponent(testarLogo, PREFERRED_SIZE, 75, PREFERRED_SIZE) - .addComponent(ouLogo, PREFERRED_SIZE, 70, PREFERRED_SIZE)) - .addGap(30) - .addGroup(aboutPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) - .addComponent(fittestLogo, PREFERRED_SIZE, 75, PREFERRED_SIZE) - .addComponent(testomatLogo, PREFERRED_SIZE, 75, PREFERRED_SIZE)) - .addGap(25) - .addGroup(aboutPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) - .addComponent(ivvesLogo, PREFERRED_SIZE, 100, PREFERRED_SIZE) - .addComponent(iv4xrLogo, PREFERRED_SIZE, 80, PREFERRED_SIZE) - .addComponent(decoderLogo, PREFERRED_SIZE, 100, PREFERRED_SIZE))) - ); - - } - - private JLabel getLogo (String iconPath) throws IOException{ - return new JLabel(new ImageIcon(SettingsDialog.loadIcon(iconPath))); - } -} diff --git a/testar/src/org/testar/settingsdialog/dialog/FilterPanel.java b/testar/src/org/testar/settingsdialog/dialog/FilterPanel.java deleted file mode 100644 index fd834942f..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/FilterPanel.java +++ /dev/null @@ -1,111 +0,0 @@ -/*************************************************************************************************** - * - * Copyright (c) 2013 - 2021 Universitat Politecnica de Valencia - www.upv.es - * Copyright (c) 2018 - 2021 Open Universiteit - www.ou.nl - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************************************/ - -package org.testar.settingsdialog.dialog; - -import org.apache.commons.lang3.StringUtils; -import org.testar.monkey.ConfigTags; -import org.testar.monkey.Settings; -import org.testar.settingsdialog.SettingsPanel; - -import javax.swing.*; - -import java.util.Arrays; - -public class FilterPanel extends SettingsPanel { - - private static final long serialVersionUID = 1572649050808020748L; - - private JLabel filterLabel = new JLabel("Filter actions on the widgets based on Tags values (regular expression):"); - private JLabel filterTags = new JLabel("Tags to apply the filters (semicolon to customize multiple Tags)"); - private JLabel killProcessLabel = new JLabel("Kill processes by name (regular expression):"); - - private JTextArea txtClickFilter = new JTextArea(); - private JTextArea txtTagsToFilter = new JTextArea(); - private JTextArea txtProcessFilter = new JTextArea(); - - public FilterPanel() { - filterLabel.setToolTipText(ToolTipTexts.label1TTT); - killProcessLabel.setToolTipText(ToolTipTexts.label2TTT); - - setLayout(null); - filterLabel.setBounds(10, 5, 600, 27); - add(filterLabel); - - txtClickFilter.setLineWrap(true); - JScrollPane clickFilterPane = new JScrollPane(txtClickFilter); - clickFilterPane.setBounds(10, 35, 600, 100); - clickFilterPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - clickFilterPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - add(clickFilterPane); - - filterTags.setBounds(10, 130, 600, 27); - add(filterTags); - - txtTagsToFilter.setLineWrap(true); - JScrollPane tagsToFilterPane = new JScrollPane(txtTagsToFilter); - tagsToFilterPane.setBounds(10, 160, 600, 50); - tagsToFilterPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - tagsToFilterPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - add(tagsToFilterPane); - - killProcessLabel.setBounds(10, 210, 600, 27); - add(killProcessLabel); - - txtProcessFilter.setLineWrap(true); - JScrollPane processFilterPane = new JScrollPane(txtProcessFilter); - processFilterPane.setBounds(10, 240, 600, 100); - processFilterPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - processFilterPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - add(processFilterPane); - } - - /** - * Populate Filter Fields from Settings structure. - * @param settings The settings to load. - */ - @Override - public void populateFrom(final Settings settings) { - txtClickFilter.setText(settings.get(ConfigTags.ClickFilter)); - txtTagsToFilter.setText(StringUtils.join(settings.get(ConfigTags.TagsToFilter), ";")); - txtProcessFilter.setText(settings.get(ConfigTags.ProcessesToKillDuringTest)); - } - - /** - * Retrieve information from the Filter GUI. - * @param settings reference to the object where the settings will be stored. - */ - @Override - public void extractInformation(final Settings settings) { - settings.set(ConfigTags.ClickFilter, txtClickFilter.getText()); - settings.set(ConfigTags.TagsToFilter, Arrays.asList(txtTagsToFilter.getText().split(";"))); - settings.set(ConfigTags.ProcessesToKillDuringTest, txtProcessFilter.getText()); - } -} diff --git a/testar/src/org/testar/settingsdialog/dialog/GeneralPanel.java b/testar/src/org/testar/settingsdialog/dialog/GeneralPanel.java deleted file mode 100644 index 4fd4d9cc7..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/GeneralPanel.java +++ /dev/null @@ -1,298 +0,0 @@ -/*************************************************************************************************** -* -* Copyright (c) 2013 - 2020 Universitat Politecnica de Valencia - www.upv.es -* Copyright (c) 2018 - 2020 Open Universiteit - www.ou.nl -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************************************/ - - -package org.testar.settingsdialog.dialog; - -import org.testar.monkey.*; -import org.testar.settingsdialog.ProtocolEditor; -import org.testar.settingsdialog.SettingsDialog; -import org.testar.settingsdialog.SettingsPanel; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.io.File; -import java.util.Arrays; -import java.util.Observable; -import java.util.Observer; - -public class GeneralPanel extends SettingsPanel implements Observer { - - private static final long serialVersionUID = -7401834140061189752L; - - private Settings settings; - private JComboBox cboxSUTconnector; - private JTextArea txtSutPath; - private JSpinner spnNumSequences; - private JSpinner spnSequenceLength; - //private JCheckBox checkStopOnFault; - private JComboBox comboBoxProtocol; - private JCheckBox compileCheckBox, checkActionVisualization; - - private JLabel labelAppName = new JLabel("Application name"); - private JLabel labelAppVersion = new JLabel("Application version"); - - private JTextField applicationNameField = new JTextField(); - private JTextField applicationVersionField = new JTextField(); - - private JLabel labelOverrideWebDriverDisplayScale = new JLabel("Override display scale"); - private JTextField overrideWebDriverDisplayScaleField = new JTextField(); - - public GeneralPanel(SettingsDialog settingsDialog) { - setLayout(null); - - addGeneralLabels(); - addGeneralControlsGlobal(settingsDialog); - addGeneralControlsLocal(); - } - - private void addGeneralControlsGlobal(SettingsDialog settingsDialog) { - cboxSUTconnector = new JComboBox<>(); - cboxSUTconnector.setModel(new DefaultComboBoxModel<>(new String[]{ - Settings.SUT_CONNECTOR_CMDLINE, - Settings.SUT_CONNECTOR_PROCESS_NAME, - Settings.SUT_CONNECTOR_WINDOW_TITLE, - Settings.SUT_CONNECTOR_WEBDRIVER - })); - cboxSUTconnector.setSelectedIndex(0); - cboxSUTconnector.setBounds(114, 12, 171, 25); - cboxSUTconnector.setToolTipText(ToolTipTexts.sutConnectorTTT); - cboxSUTconnector.setMaximumRowCount(3); - add(cboxSUTconnector); - - txtSutPath = new JTextArea(); - txtSutPath.setLineWrap(true); - txtSutPath.setToolTipText(ToolTipTexts.sutPathTTT); - - spnNumSequences = new JSpinner(); - spnNumSequences.setBounds(160, 161, 71, 25); - spnNumSequences.setModel(new SpinnerNumberModel(1, 1, null, 1)); - spnNumSequences.setToolTipText(ToolTipTexts.nofSequencesTTT); - add(spnNumSequences); - - spnSequenceLength = new JSpinner(); - spnSequenceLength.setBounds(160, 199, 71, 25); - spnSequenceLength.setModel(new SpinnerNumberModel(999, 1, null, 1)); - spnSequenceLength.setToolTipText(ToolTipTexts.sequencesActionsTTT); - add(spnSequenceLength); - - comboBoxProtocol = new JComboBox<>(); - comboBoxProtocol.setBounds(350, 161, 260, 25); - String[] sutSettings = new File(Main.settingsDir) - .list((current, name) -> new File(current, name).isDirectory()); - Arrays.sort(sutSettings); - comboBoxProtocol.setModel(new DefaultComboBoxModel<>(sutSettings)); - comboBoxProtocol.setMaximumRowCount(sutSettings.length > 16 ? 16 : sutSettings.length); - - // Pass button click to settings dialog - MyItemListener myItemListener = new MyItemListener(); - myItemListener.addObserver(settingsDialog); - myItemListener.addObserver(this); - comboBoxProtocol.addItemListener(myItemListener); - comboBoxProtocol.setToolTipText(ToolTipTexts.comboBoxProtocolTTT); - add(comboBoxProtocol); - - compileCheckBox = new JCheckBox("Always compile protocol"); - compileCheckBox.setBounds(286, 199, 192, 21); - compileCheckBox.setToolTipText(ToolTipTexts.lblCompileTTT); - add(compileCheckBox); - - /*checkStopOnFault = new JCheckBox("Stop Test on Fault"); - checkStopOnFault.setBounds(10, 240, 192, 21); - checkStopOnFault.setToolTipText(checkStopOnFaultTTT); - add(checkStopOnFault);*/ - - checkActionVisualization = new JCheckBox("Visualize actions on GUI"); - checkActionVisualization.setBounds(10, 240, 192, 21); - //checkActionVisualization.setToolTipText(checkStopOnFaultTTT); - add(checkActionVisualization); - - labelAppName.setBounds(330, 242, 150, 27); - labelAppName.setToolTipText(ToolTipTexts.applicationNameTTT); - add(labelAppName); - applicationNameField.setBounds(480, 242, 125, 27); - applicationNameField.setToolTipText(ToolTipTexts.applicationNameTTT); - add(applicationNameField); - - labelAppVersion.setBounds(330, 280, 150, 27); - labelAppVersion.setToolTipText(ToolTipTexts.applicationVersionTTT); - add(labelAppVersion); - applicationVersionField.setBounds(480, 280, 125, 27); - applicationVersionField.setToolTipText(ToolTipTexts.applicationVersionTTT); - add(applicationVersionField); - - // Hide the override webdriver display scale fields by default, only show them when a webdriver protocol is selected. - setOverrideWebDriverDisplayScaleVisibility(false); - labelOverrideWebDriverDisplayScale.setBounds(330, 320, 150, 27); - labelOverrideWebDriverDisplayScale.setToolTipText(ToolTipTexts.overrideWebDriverDisplayScaleTTT); - add(labelOverrideWebDriverDisplayScale); - overrideWebDriverDisplayScaleField.setBounds(480, 320, 125, 27); - overrideWebDriverDisplayScaleField.setToolTipText(ToolTipTexts.overrideWebDriverDisplayScaleTTT); - add(overrideWebDriverDisplayScaleField); - } - - private void setOverrideWebDriverDisplayScaleVisibility(boolean isVisible){ - labelOverrideWebDriverDisplayScale.setVisible(isVisible); - overrideWebDriverDisplayScaleField.setVisible(isVisible); - } - - @Override - public void update(Observable o, Object arg) { - boolean showWidgets = arg.toString().contains("webdriver"); - setOverrideWebDriverDisplayScaleVisibility(showWidgets); - } - - private void addGeneralControlsLocal() { - JButton btnSutPath = new JButton("Select SUT"); - btnSutPath.setBounds(520, 11, 90, 25); - btnSutPath.addActionListener(this::btnSutPathActionPerformed); - btnSutPath.setToolTipText(ToolTipTexts.btnSelectSUTTTT); - add(btnSutPath); - - JButton btnEditProtocol = new JButton("Edit Protocol"); - btnEditProtocol.setBounds(510, 199, 100, 25); - btnEditProtocol.addActionListener(this::btnEditProtocolActionPerformed); - btnEditProtocol.setToolTipText(ToolTipTexts.btnEditProtocolTTT); - btnEditProtocol.setMaximumSize(new Dimension(160, 35)); - btnEditProtocol.setMinimumSize(new Dimension(160, 35)); - btnEditProtocol.setPreferredSize(new Dimension(160, 35)); - add(btnEditProtocol); - - JScrollPane scrollPane = new JScrollPane(); - scrollPane.setBounds(10, 42, 600, 108); - add(scrollPane); - scrollPane.setViewportView(txtSutPath); - } - - private void addGeneralLabels() { - JLabel lblSUTconnector = new JLabel("SUT connector:"); - lblSUTconnector.setBounds(10, 11, 97, 20); - lblSUTconnector.setToolTipText(ToolTipTexts.sutConnectorTTT); - add(lblSUTconnector); - - JLabel lblNofSequences = new JLabel("Number of Sequences:"); - lblNofSequences.setBounds(10, 164, 135, 14); - lblNofSequences.setToolTipText(ToolTipTexts.nofSequencesTTT); - add(lblNofSequences); - - JLabel lblSequenceActions = new JLabel("Sequence actions:"); - lblSequenceActions.setBounds(10, 202, 148, 14); - lblSequenceActions.setToolTipText(ToolTipTexts.sequencesActionsTTT); - add(lblSequenceActions); - - JLabel lblProtocol = new JLabel("Protocol:"); - lblProtocol.setBounds(286, 164, 64, 14); - lblProtocol.setToolTipText(ToolTipTexts.comboBoxProtocolTTT); - add(lblProtocol); - } - - private void btnSutPathActionPerformed(ActionEvent evt) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.FILES_ONLY); - fd.setCurrentDirectory(new File(settings.get(ConfigTags.SUTConnectorValue)).getParentFile()); - - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - - if (settings.get(ConfigTags.SUTConnector) - .equals(Settings.SUT_CONNECTOR_WEBDRIVER)) { - // When using the WEB_DRIVER connector, only replace webdriver path - String[] orgSettingParts = txtSutPath.getText().split(" "); - orgSettingParts[0] = "\"" + file + "\""; - txtSutPath.setText(String.join(" ", orgSettingParts)); - } - else { - // Set the text from settings in txtSutPath - txtSutPath.setText(file); - } - } - } - - private void btnEditProtocolActionPerformed(ActionEvent evt) { - JDialog dialog = new ProtocolEditor(Main.settingsDir, settings.get(ConfigTags.ProtocolClass)); - dialog.setModalityType(JDialog.ModalityType.APPLICATION_MODAL); - dialog.setVisible(true); - } - - /** - * Populate JPanelGeneral from Settings structure. - * - * @param settings The settings to load. - */ - @Override - public void populateFrom(final Settings settings) { - this.settings = settings; - - cboxSUTconnector.setSelectedItem(settings.get(ConfigTags.SUTConnector)); - //checkStopOnFault.setSelected(settings.get(ConfigTags.StopGenerationOnFault)); - checkActionVisualization.setSelected(settings.get(ConfigTags.VisualizeActions)); - txtSutPath.setText(settings.get(ConfigTags.SUTConnectorValue)); - comboBoxProtocol.setSelectedItem(settings.get(ConfigTags.ProtocolClass).split("/")[0]); - spnNumSequences.setValue(settings.get(ConfigTags.Sequences)); - spnSequenceLength.setValue(settings.get(ConfigTags.SequenceLength)); - compileCheckBox.setSelected(settings.get(ConfigTags.AlwaysCompile)); - applicationNameField.setText(settings.get(ConfigTags.ApplicationName)); - applicationVersionField.setText(settings.get(ConfigTags.ApplicationVersion)); - overrideWebDriverDisplayScaleField.setText(settings.get(ConfigTags.OverrideWebDriverDisplayScale)); - } - - /** - * Retrieve information from the JPanelGeneral GUI. - * - * @param settings reference to the object where the settings will be stored. - */ - @Override - public void extractInformation(final Settings settings) { - settings.set(ConfigTags.SUTConnector, (String) cboxSUTconnector.getSelectedItem()); - settings.set(ConfigTags.SUTConnectorValue, txtSutPath.getText()); - //settings.set(ConfigTags.StopGenerationOnFault, checkStopOnFault.isSelected()); - settings.set(ConfigTags.VisualizeActions, checkActionVisualization.isSelected()); - settings.set(ConfigTags.SUTConnectorValue, txtSutPath.getText()); - settings.set(ConfigTags.Sequences, (Integer) spnNumSequences.getValue()); - settings.set(ConfigTags.SequenceLength, (Integer) spnSequenceLength.getValue()); - settings.set(ConfigTags.AlwaysCompile, compileCheckBox.isSelected()); - settings.set(ConfigTags.ApplicationName, applicationNameField.getText()); - settings.set(ConfigTags.ApplicationVersion, applicationVersionField.getText()); - settings.set(ConfigTags.OverrideWebDriverDisplayScale, overrideWebDriverDisplayScaleField.getText()); - } - - public class MyItemListener extends Observable implements ItemListener { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - setChanged(); - notifyObservers(e.getItem()); - } - } - } -} diff --git a/testar/src/org/testar/settingsdialog/dialog/MiscPanel.java b/testar/src/org/testar/settingsdialog/dialog/MiscPanel.java deleted file mode 100644 index a9095e0dd..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/MiscPanel.java +++ /dev/null @@ -1,332 +0,0 @@ -/*************************************************************************************************** - * - * Copyright (c) 2013 - 2020 Universitat Politecnica de Valencia - www.upv.es - * Copyright (c) 2018 - 2020 Open Universiteit - www.ou.nl - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************************************/ - - -package org.testar.settingsdialog.dialog; - -import org.testar.monkey.Pair; -import org.testar.monkey.Util; -import org.testar.monkey.ConfigTags; -import org.testar.monkey.Settings; -import org.testar.settingsdialog.SettingsPanel; - -import javax.swing.*; - -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.File; -import java.util.List; - -import static javax.swing.GroupLayout.DEFAULT_SIZE; -import static javax.swing.GroupLayout.PREFERRED_SIZE; -import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; -import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED; - -public class MiscPanel extends SettingsPanel { - - private static final long serialVersionUID = 8435304494218446662L; - - private File currentDirectory; - private JTable tblCopyFromTo; - private JTable tblDelete; - private JTextField txtOutputDir; - private JTextField txtTempDir; - - private JCheckBox onlySaveFaultySequences; - - public MiscPanel() { - // Init the global items - initMiscGlobal(); - - // Init the local items - JScrollPane jScrollPane4 = new JScrollPane(); - jScrollPane4.setViewportView(tblDelete); - - JScrollPane jScrollPane5 = new JScrollPane(); - jScrollPane5.setViewportView(tblCopyFromTo); - - JLabel jLabel16 = new JLabel("Copy Files on SUT Startup:"); - jLabel16.setToolTipText(ToolTipTexts.copyFilesTTT); - JLabel jLabel8 = new JLabel("Output Directory:"); - JLabel jLabel9 = new JLabel("Temp Directory:"); - JLabel jLabel20 = new JLabel("Delete Files on SUT Startup:"); - jLabel20.setToolTipText(ToolTipTexts.deleteFiles); - - JButton btnSetOutputDir = new JButton("Select"); - btnSetOutputDir.addActionListener(this::btnSetOutputDirActionPerformed); - btnSetOutputDir.setEnabled(true); - - JButton btnSetTempDir = new JButton("Select"); - btnSetTempDir.addActionListener(this::btnSetTempDirActionPerformed); - btnSetTempDir.setEnabled(true); - - onlySaveFaultySequences = new JCheckBox("Only Save Faulty Sequences"); - onlySaveFaultySequences.setToolTipText("Only Save Faulty Sequences"); - - GroupLayout gl_jPanelMisc = new GroupLayout(this); - this.setLayout(gl_jPanelMisc); - gl_jPanelMisc.setHorizontalGroup( - gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(gl_jPanelMisc.createSequentialGroup() - .addContainerGap() - .addGroup(gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane5) - .addComponent(jScrollPane4) - .addComponent(onlySaveFaultySequences) - .addGroup(gl_jPanelMisc.createSequentialGroup() - .addGroup(gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(gl_jPanelMisc.createSequentialGroup() - .addGroup(gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.LEADING, false) - .addGroup(gl_jPanelMisc.createSequentialGroup() - .addComponent(jLabel8, PREFERRED_SIZE, 92, PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(txtOutputDir, PREFERRED_SIZE, 346, PREFERRED_SIZE)) - .addGroup(gl_jPanelMisc.createSequentialGroup() - .addComponent(jLabel9, PREFERRED_SIZE, 92, PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(txtTempDir, PREFERRED_SIZE, 346, PREFERRED_SIZE)) - .addComponent(jLabel16, PREFERRED_SIZE, 393, PREFERRED_SIZE)) - .addPreferredGap(RELATED) - .addGroup(gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(btnSetOutputDir, PREFERRED_SIZE, 90, PREFERRED_SIZE) - .addComponent(btnSetTempDir, PREFERRED_SIZE, 90, PREFERRED_SIZE))) - .addComponent(jLabel20, PREFERRED_SIZE, 393, PREFERRED_SIZE)) - .addGap(0, 0, Short.MAX_VALUE))) - .addContainerGap()) - ); - gl_jPanelMisc.setVerticalGroup( - gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(gl_jPanelMisc.createSequentialGroup() - .addContainerGap() - .addGroup(gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(txtOutputDir, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) - .addComponent(jLabel8) - .addComponent(btnSetOutputDir, PREFERRED_SIZE, 20, PREFERRED_SIZE)) - .addPreferredGap(RELATED) - .addGroup(gl_jPanelMisc.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(txtTempDir, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) - .addComponent(jLabel9) - .addComponent(btnSetTempDir, PREFERRED_SIZE, 20, PREFERRED_SIZE)) - .addPreferredGap(UNRELATED) - .addComponent(jLabel16) - .addPreferredGap(RELATED) - .addComponent(jScrollPane5, PREFERRED_SIZE, 101, PREFERRED_SIZE) - .addPreferredGap(UNRELATED) - .addComponent(jLabel20) - .addPreferredGap(RELATED) - .addComponent(jScrollPane4, PREFERRED_SIZE, 103, PREFERRED_SIZE) - .addContainerGap(22, Short.MAX_VALUE) - .addComponent(onlySaveFaultySequences)) - ); - - } - - private void initMiscGlobal() { - tblDelete = new JTable(); - tblDelete.setModel(new javax.swing.table.DefaultTableModel( - new Object[50][1], new String[]{"File / Directory"}) { - private static final long serialVersionUID = 1L; - Class[] types = new Class[]{String.class}; - - public Class getColumnClass(int columnIndex) { - return types[columnIndex]; - } - }); - tblDelete.setToolTipText("\nFiles to delete before SUT start: Certain SUTs generate configuration files, temporary files and files
\nthat save the system's state. This might be problematic during sequence replay, when you want a
\nsystem to always start in the same state. Therefore, you can specify these files, to be deleted
\nbefore the SUT gets started. If you double-click the text-area a file dialog will pop up which allows
\nselecting files and directories to be deleted.\n"); - tblDelete.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent evt) { - tblDeleteMouseClicked(evt); - } - }); - - tblCopyFromTo = new JTable(); - tblCopyFromTo.setModel(new javax.swing.table.DefaultTableModel( - new Object[50][2], new String[]{ - "Source File / Directory", "Destination"} - ) { - private static final long serialVersionUID = 1L; - Class[] types = new Class[]{String.class, String.class}; - - public Class getColumnClass(int columnIndex) { - return types[columnIndex]; - } - }); - tblCopyFromTo.setToolTipText("\nFiles to copy before SUT start. It is useful to restore certain
\n configuration files to their default. Therefore you can define pairs of paths (copy from / to).
\nTESTAR will copy each specified file from the given source location to the given destination.
\nSimply double-click the text-area and a file dialog will pop up.\n"); - tblCopyFromTo.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent evt) { - tblCopyFromToMouseClicked(evt); - } - }); - - txtOutputDir = new JTextField(); - txtOutputDir.setEditable(false); - - txtTempDir = new JTextField(); - txtTempDir.setEditable(false); - } - - private void btnSetOutputDirActionPerformed(ActionEvent evt) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - fd.setCurrentDirectory(currentDirectory); - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - txtOutputDir.setText(file); - } - } - - private void btnSetTempDirActionPerformed(ActionEvent evt) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - fd.setCurrentDirectory(currentDirectory); - - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - txtTempDir.setText(file); - } - } - - private void tblCopyFromToMouseClicked(MouseEvent evt) { - if (tblCopyFromTo.getSelectedColumn() >= 0 && tblCopyFromTo.getSelectedRow() >= 0) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - tblCopyFromTo.setValueAt(file, tblCopyFromTo.getSelectedRow(), tblCopyFromTo.getSelectedColumn()); - } - else { - tblCopyFromTo.setValueAt(null, tblCopyFromTo.getSelectedRow(), tblCopyFromTo.getSelectedColumn()); - } - } - } - - private void tblDeleteMouseClicked(MouseEvent evt) { - if (tblDelete.getSelectedRow() >= 0 && tblDelete.getSelectedColumn() >= 0) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - tblDelete.setValueAt(file, tblDelete.getSelectedRow(), tblDelete.getSelectedColumn()); - } - else { - tblDelete.setValueAt(null, tblDelete.getSelectedRow(), tblDelete.getSelectedColumn()); - } - } - } - - /** - * Populate Misc Fields from Settings structure. - * - * @param settings The settings to load. - */ - @Override - public void populateFrom(final Settings settings) { - onlySaveFaultySequences.setSelected(settings.get(ConfigTags.OnlySaveFaultySequences)); - currentDirectory = new File(settings.get(ConfigTags.OutputDir)).getParentFile(); - - txtOutputDir.setText(settings.get(ConfigTags.OutputDir)); - txtTempDir.setText(settings.get(ConfigTags.TempDir)); - - for (int i = 0; i < tblCopyFromTo.getRowCount(); i++) { - tblCopyFromTo.setValueAt(null, i, 0); - tblCopyFromTo.setValueAt(null, i, 1); - } - - int i = 0; - for (Pair fromTo : settings.get(ConfigTags.CopyFromTo)) { - tblCopyFromTo.setValueAt(fromTo.left(), i, 0); - tblCopyFromTo.setValueAt(fromTo.right(), i, 1); - i++; - } - - for (i = 0; i < tblDelete.getRowCount(); i++) { - tblDelete.setValueAt(null, i, 0); - } - - i = 0; - for (String f : settings.get(ConfigTags.Delete)) { - tblDelete.setValueAt(f, i, 0); - i++; - } - } - - /** - * Retrieve information from the Misc GUI. - * - * @param settings reference to the object where the settings will be stored. - */ - @Override - public void extractInformation(final Settings settings) { - settings.set(ConfigTags.OnlySaveFaultySequences, onlySaveFaultySequences.isSelected()); - settings.set(ConfigTags.OutputDir, txtOutputDir.getText()); - settings.set(ConfigTags.TempDir, txtTempDir.getText()); - - List> copyFromTo = Util.newArrayList(); - for (int i = 0; i < tblCopyFromTo.getRowCount(); i++) { - String left = (String) tblCopyFromTo.getValueAt(i, 0); - String right = (String) tblCopyFromTo.getValueAt(i, 1); - - if (left != null && right != null) { - copyFromTo.add(Pair.from(left, right)); - } - } - settings.set(ConfigTags.CopyFromTo, copyFromTo); - - List delete = Util.newArrayList(); - for (int i = 0; i < tblDelete.getRowCount(); i++) { - String value = (String) tblDelete.getValueAt(i, 0); - if (value != null) { - delete.add(value); - } - } - settings.set(ConfigTags.Delete, delete); - } - - @Override - public void checkSettings() throws IllegalStateException { - for (int i = 0; i < tblCopyFromTo.getRowCount(); i++) { - String left = (String) tblCopyFromTo.getValueAt(i, 0); - String right = (String) tblCopyFromTo.getValueAt(i, 1); - - if (left != null || right != null) { - if ((left != null && right == null) || - (left == null && right != null) || - left.trim().equals("") || - right.trim().equals("")) { - throw new IllegalStateException( - "CopyFromTo Table has unfinished entries!"); - } - } - } - } -} diff --git a/testar/src/org/testar/settingsdialog/dialog/OraclePanel.java b/testar/src/org/testar/settingsdialog/dialog/OraclePanel.java deleted file mode 100644 index 6d3ac66b8..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/OraclePanel.java +++ /dev/null @@ -1,177 +0,0 @@ -/*************************************************************************************************** - * - * Copyright (c) 2013 - 2021 Universitat Politecnica de Valencia - www.upv.es - * Copyright (c) 2018 - 2021 Open Universiteit - www.ou.nl - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************************************/ - - -package org.testar.settingsdialog.dialog; - -import org.testar.monkey.ConfigTags; -import org.testar.monkey.Settings; -import org.testar.settingsdialog.SettingsPanel; -import org.testar.visualvalidation.VisualValidationSettings; - -import org.apache.commons.lang3.StringUtils; -import org.testar.extendedsettings.ExtendedSettingsFactory; - -import javax.swing.*; - -import java.util.Arrays; - -public class OraclePanel extends SettingsPanel { - - private static final long serialVersionUID = -8633257917450402330L; - - private JLabel suspiciousTitleLabel = new JLabel("Suspicious Titles based on Tags values (regular expression)"); - private JLabel suspiciousTitleTagsLabel = new JLabel("Tags to apply the Suspicious Titles (semicolon to customize multiple Tags)"); - private JLabel suspiciousProcessLabel = new JLabel("Suspicious Process Output (regular expression)"); - private JLabel freezeTimeLabel = new JLabel("Freeze Time:"); - private JLabel secondsLabel = new JLabel("seconds"); - - private JTextArea txtSuspTitles = new JTextArea(); - private JTextArea txtTagsForSuspTitles = new JTextArea(); - private JTextArea txtProcTitles = new JTextArea(); - - private JCheckBox processCheckBox; - private JSpinner spnFreezeTime; - - private JCheckBox enableWebConsoleErrorOracle; - private JTextArea txtWebConsoleErrorPattern = new JTextArea(); - private JCheckBox enableWebConsoleWarningOracle; - private JTextArea txtWebConsoleWarningPattern = new JTextArea(); - - private JCheckBox enableVisualValidationCheckBox; - - public OraclePanel() { - setLayout(null); - - suspiciousTitleLabel.setBounds(10, 5, 600, 27); - suspiciousTitleLabel.setToolTipText(ToolTipTexts.suspiciousTitlesTTT); - add(suspiciousTitleLabel); - - txtSuspTitles.setLineWrap(true); - JScrollPane suspTitlePane = new JScrollPane(txtSuspTitles); - suspTitlePane.setBounds(10, 35, 600, 100); - suspTitlePane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - suspTitlePane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - add(suspTitlePane); - - suspiciousTitleTagsLabel.setBounds(10, 130, 600, 27); - add(suspiciousTitleTagsLabel); - - txtTagsForSuspTitles.setLineWrap(true); - JScrollPane tagsForSuspTitlesPane = new JScrollPane(txtTagsForSuspTitles); - tagsForSuspTitlesPane.setBounds(10, 160, 600, 50); - tagsForSuspTitlesPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - tagsForSuspTitlesPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - add(tagsForSuspTitlesPane); - - suspiciousProcessLabel.setBounds(10, 220, 280, 27); - add(suspiciousProcessLabel); - - processCheckBox = new JCheckBox("Enable Process Listener"); - processCheckBox.setBounds(300, 220, 200, 27); - add(processCheckBox); - - txtProcTitles.setLineWrap(true); - JScrollPane suspiciousProcessPane = new JScrollPane(txtProcTitles); - suspiciousProcessPane.setBounds(10, 250, 600, 50); - suspiciousProcessPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - suspiciousProcessPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - add(suspiciousProcessPane); - - enableWebConsoleErrorOracle = new JCheckBox("Enable Web Console Error Oracle"); - enableWebConsoleErrorOracle.setBounds(10, 300, 300, 27); - enableWebConsoleErrorOracle.setToolTipText("Enable Web Console Error Oracle"); - add(enableWebConsoleErrorOracle); - - enableWebConsoleWarningOracle = new JCheckBox("Enable Web Console Warning Oracle"); - enableWebConsoleWarningOracle.setBounds(10, 330, 300, 27); - enableWebConsoleWarningOracle.setToolTipText("Enable Web Console Warning Oracle"); - add(enableWebConsoleWarningOracle); - - // Disable the visualization until the implementation is ready - //enableVisualValidationCheckBox = new JCheckBox("Enable visual validation"); - //enableVisualValidationCheckBox.setBounds(10, 330, 180, 27); - //enableVisualValidationCheckBox.setToolTipText(ToolTipTexts.enableVisualValidationTTT); - //add(enableVisualValidationCheckBox); - - freezeTimeLabel.setBounds(300, 330, 80, 27); - add(freezeTimeLabel); - spnFreezeTime = new JSpinner(); - spnFreezeTime.setModel(new SpinnerNumberModel(1.0d, 1.0d, null, 1.0d)); - spnFreezeTime.setBounds(390, 330, 50, 27); - add(spnFreezeTime); - secondsLabel.setBounds(450, 330, 50, 27); - add(secondsLabel); - } - - /** - * Populate Oracle Fields from Settings structure. - * @param settings The settings to load. - */ - @Override - public void populateFrom(final Settings settings) { - txtSuspTitles.setText(settings.get(ConfigTags.SuspiciousTitles)); - txtTagsForSuspTitles.setText(StringUtils.join(settings.get(ConfigTags.TagsForSuspiciousOracle), ";")); - processCheckBox.setSelected(settings.get(ConfigTags.ProcessListenerEnabled)); - txtProcTitles.setText(settings.get(ConfigTags.SuspiciousProcessOutput)); - spnFreezeTime.setValue(settings.get(ConfigTags.TimeToFreeze)); - // Web Browser Console Oracles elements - enableWebConsoleErrorOracle.setSelected(settings.get(ConfigTags.WebConsoleErrorOracle)); - txtWebConsoleErrorPattern.setText(settings.get(ConfigTags.WebConsoleErrorPattern)); - enableWebConsoleWarningOracle.setSelected(settings.get(ConfigTags.WebConsoleWarningOracle)); - txtWebConsoleWarningPattern.setText(settings.get(ConfigTags.WebConsoleWarningPattern)); - // Visual validation elements - VisualValidationSettings visualSetting = ExtendedSettingsFactory.createVisualValidationSettings(); - // Disable the visualization until the implementation is ready - //enableVisualValidationCheckBox.setSelected(visualSetting.enabled); - } - - /** - * Retrieve information from the Oracle GUI. - * @param settings reference to the object where the settings will be stored. - */ - @Override - public void extractInformation(final Settings settings) { - settings.set(ConfigTags.SuspiciousTitles, txtSuspTitles.getText()); - settings.set(ConfigTags.TagsForSuspiciousOracle, Arrays.asList(txtTagsForSuspTitles.getText().split(";"))); - settings.set(ConfigTags.ProcessListenerEnabled, processCheckBox.isSelected()); - settings.set(ConfigTags.SuspiciousProcessOutput, txtProcTitles.getText()); - settings.set(ConfigTags.TimeToFreeze, (Double) spnFreezeTime.getValue()); - // Web Browser Console Oracles elements - settings.set(ConfigTags.WebConsoleErrorOracle, enableWebConsoleErrorOracle.isSelected()); - settings.set(ConfigTags.WebConsoleErrorPattern, txtWebConsoleErrorPattern.getText()); - settings.set(ConfigTags.WebConsoleWarningOracle, enableWebConsoleWarningOracle.isSelected()); - settings.set(ConfigTags.WebConsoleWarningPattern, txtWebConsoleWarningPattern.getText()); - // Visual validation elements - VisualValidationSettings visualSetting = ExtendedSettingsFactory.createVisualValidationSettings(); - // Disable the visualization until the implementation is ready - //visualSetting.enabled = enableVisualValidationCheckBox.isSelected(); - } -} diff --git a/testar/src/org/testar/settingsdialog/dialog/ScanningReportDialog.java b/testar/src/org/testar/settingsdialog/dialog/ScanningReportDialog.java deleted file mode 100644 index 43a878cb0..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/ScanningReportDialog.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.testar.settingsdialog.dialog; - -import org.testar.settingsdialog.codeanalysis.RepositoryLanguage; -import org.testar.settingsdialog.codeanalysis.RepositoryLanguageComposition; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.WindowEvent; -import java.math.RoundingMode; - -public class ScanningReportDialog extends JFrame { - private RepositoryLanguageComposition repositoryLanguageComposition; - private JTable reportTable; - private JScrollPane reportTableContainer; - private JButton closeButton; - private final static String CLOSE_BUTTON = "Close"; - private final static String WINDOW_TITLE = "Full report"; - private final static Object[] COLUMN_NAMES = new Object[]{"No", "Language", "Composition"}; - private final static int[] WINDOW_SIZE = new int[]{400, 400}; - - public ScanningReportDialog(RepositoryLanguageComposition repositoryLanguageComposition) throws HeadlessException { - this.repositoryLanguageComposition = repositoryLanguageComposition; - initCloseButton(); - initTable(); - initLayoutProperties(); - initLayoutContent(); - calculateWindowLocation(); - } - - private void initCloseButton() { - closeButton = new JButton(CLOSE_BUTTON); - closeButton.addActionListener((event) -> { - dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); - }); - closeButton.setAlignmentX(Component.CENTER_ALIGNMENT); - } - - private void initTable() { - reportTableContainer = new JScrollPane(); - reportTable = new JTable(getTableData(), COLUMN_NAMES); - reportTableContainer.setViewportView(reportTable); - } - - - private Object[][] getTableData() { - Object[][] tableData = new Object[repositoryLanguageComposition.getRepositoryLanguages().size()][]; - for (int i = 0; i < tableData.length; i++) { - RepositoryLanguage language = repositoryLanguageComposition.getRepositoryLanguages().get(i); - tableData[i] = new Object[]{i, language.getSupportedLanguage().getName(), language.getPercentage().setScale(0, RoundingMode.HALF_UP).toString() + "%"}; - } - return tableData; - } - - private void initLayoutProperties() { - setTitle(WINDOW_TITLE); - setSize(WINDOW_SIZE[0], WINDOW_SIZE[1]); - setVisible(true); - setResizable(false); - } - - private void initLayoutContent() { - getContentPane().add(reportTable.getTableHeader()); - getContentPane().add(reportTableContainer); - getContentPane().add(Box.createRigidArea(new Dimension(WINDOW_SIZE[0], 6))); - getContentPane().add(closeButton); - getContentPane().add(Box.createRigidArea(new Dimension(WINDOW_SIZE[0], 6))); - setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); - } - - private void calculateWindowLocation() { - Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); - this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2); - } -} - diff --git a/testar/src/org/testar/settingsdialog/dialog/StateModelPanel.java b/testar/src/org/testar/settingsdialog/dialog/StateModelPanel.java deleted file mode 100644 index 5078a41b1..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/StateModelPanel.java +++ /dev/null @@ -1,440 +0,0 @@ -/*************************************************************************************************** -* -* Copyright (c) 2017, 2018, 2019 Open Universiteit - www.ou.nl -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************************************/ - - -package org.testar.settingsdialog.dialog; - -import org.testar.CodingManager; -import org.testar.StateManagementTags; -import org.testar.statemodel.analysis.AnalysisManager; -import org.testar.statemodel.analysis.webserver.JettyServer; -import org.testar.statemodel.persistence.orientdb.entity.Config; -import org.testar.monkey.alayer.Tag; -import org.testar.monkey.ConfigTags; -import org.testar.monkey.Settings; -import org.testar.settingsdialog.SettingsPanel; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Panel with settings for the state model inference module. - */ -public class StateModelPanel extends SettingsPanel { - - private static final long serialVersionUID = -2815422165938356237L; - private JLabel label1 = new JLabel("State model enabled"); - private JLabel label2 = new JLabel("DataStore"); - private JLabel label3 = new JLabel("DataStoreType"); - private JLabel label4 = new JLabel("DataStoreServer"); - private JLabel label5 = new JLabel("DataStoreDB"); - private JLabel label6 = new JLabel("DataStoreUser"); - private JLabel label7 = new JLabel("DataStorePassword"); - private JLabel label8 = new JLabel("DataStoreMode"); - private JLabel label9 = new JLabel("Reset database"); - private JLabel label12 = new JLabel("AccessBridge enabled"); - private JLabel label13 = new JLabel("DataStoreDirectory"); - private JLabel label14 = new JLabel(); - private JLabel label15 = new JLabel("Action selection"); - private JLabel label16 = new JLabel("Store Widgets"); - - - private JCheckBox stateModelEnabledChkBox = new JCheckBox(); - private JCheckBox stateModelWidgetStoreChkBox = new JCheckBox(); - private JTextField dataStoreTextfield = new JTextField(); - private JTextField dataStoreServerTextfield = new JTextField(); - private JTextField dataStoreDBTextfield = new JTextField(); - private JTextField dataStoreUserTextfield = new JTextField(); - private JPasswordField dataStorePasswordfield = new JPasswordField(); - private JCheckBox resetDatabaseCheckbox = new JCheckBox(); - private JComboBox dataStoreModeBox = new JComboBox<>(new String[]{"none", "instant", "delayed", "hybrid"}); - private JComboBox actionSelectionBox = new JComboBox<>(new String[]{"Random selection", "Unvisited actions first"}); - private JComboBox dataStoreTypeBox = new JComboBox<>(new String[]{"remote", "plocal"}); - private Set components; - private JCheckBox accessBridgeEnabledBox = new JCheckBox(); - private JTextField dataStoreDirectoryField = new JTextField(); - private JButton dirButton = new JButton(".."); - private JButton stateTagsButton = new JButton("Advanced"); - private AbstractStateSettings stateTagsDialog; - private JButton analysisButton = new JButton("Analysis"); - private Tag[] allStateManagementTags; - private Tag[] selectedStateManagementTags; - - private String outputDir; - - private StateModelPanel(){ - super(); - } - - /** - * Create and Initialize StateModelPanel. - * @return StateModelPanel. - */ - public static StateModelPanel createStateModelPanel() { - StateModelPanel panel = new StateModelPanel(); - panel.initialize(); - return panel; - } - - /** - * Initialize panel. - */ - private void initialize() { - // fetch the available state management tags - allStateManagementTags = StateManagementTags.getAllTags().toArray(new Tag[0]); - // add the components that can be enabled/disabled to the set - components = new HashSet<>(); - components.add(dataStoreTextfield); - components.add(dataStoreTypeBox); - components.add(dataStoreServerTextfield); - components.add(dataStoreDirectoryField); - components.add(dataStoreDBTextfield); - components.add(dataStoreUserTextfield); - components.add(dataStorePasswordfield); - components.add(resetDatabaseCheckbox); - components.add(dataStoreModeBox); - components.add(accessBridgeEnabledBox); - components.add(dirButton); - components.add(analysisButton); - components.add(stateTagsButton); - components.add(actionSelectionBox); - components.add(stateModelWidgetStoreChkBox); - - // add the components to the panel - setLayout(null); - label1.setBounds(10,14,150,27); - add(label1); - stateModelEnabledChkBox.setBounds(160,14,50,27); - stateModelEnabledChkBox.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - components.forEach((component) -> component.setEnabled(stateModelEnabledChkBox.isSelected())); - if (stateModelEnabledChkBox.isSelected()) { - checkDataType(); - } - checkAnalysisButtonActive(); - } - }); - add(stateModelEnabledChkBox); - - label2.setBounds(10,52,150,27); - add(label2); - dataStoreTextfield.setBounds(160,52,125,27); - add(dataStoreTextfield); - - label3.setBounds(10,90,150,27); - add(label3); - dataStoreTypeBox.setBounds(160,90,125,27); - dataStoreTypeBox.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - checkDataType(); - } - }); - add(dataStoreTypeBox); - - label4.setBounds(10,128,150,27); - add(label4); - dataStoreServerTextfield.setBounds(160,128,125,27); - add(dataStoreServerTextfield); - - label13.setBounds(10,166,150,27); - add(label13); - dataStoreDirectoryField.setBounds(160,166,125,27); - dataStoreDirectoryField.setEditable(false); - add(dataStoreDirectoryField); - - dirButton.setBounds(290, 166, 20, 27); - dirButton.addActionListener(this::chooseFileActionPerformed); - dirButton.setToolTipText("Select the 'databases' folder in your orientdb installation. Make sure the OrientDB server is not running."); - add(dirButton); - - label5.setBounds(10,204,150,27); - add(label5); - dataStoreDBTextfield.setBounds(160,204,125,27); - add(dataStoreDBTextfield); - - label6.setBounds(10,242,150,27); - add(label6); - dataStoreUserTextfield.setBounds(160,242,125,27); - add(dataStoreUserTextfield); - - label7.setBounds(10,280,150,27); - add(label7); - dataStorePasswordfield.setBounds(160,280,125,27); - add(dataStorePasswordfield); - - label8.setBounds(10,318,150,27); - add(label8); - dataStoreModeBox.setBounds(160,318,125,27); - add(dataStoreModeBox); - - // NEW COLUMN - label16.setBounds(330, 52, 150, 27); - add(label16); - stateModelWidgetStoreChkBox.setBounds(480, 52, 50, 27); - add(stateModelWidgetStoreChkBox); - - label12.setBounds(330, 90, 150, 27); - add(label12); - accessBridgeEnabledBox.setBounds(480, 90, 50, 27); - add(accessBridgeEnabledBox); - - label9.setBounds(330,128,150,27); - add(label9); - resetDatabaseCheckbox.setBounds(480, 128, 50, 27); - resetDatabaseCheckbox.setToolTipText("This will reset the database. All stored information will be lost."); - add(resetDatabaseCheckbox); - - analysisButton.setBounds(330, 166, 150, 27); - analysisButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openServer(); - checkAnalysisButtonActive(); - } - }); - add(analysisButton); - - stateTagsButton.setBounds(330, 204, 150, 27); - stateTagsButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openStateTagSelection(); - } - }); - add(stateTagsButton); - - label15.setBounds(330,242,100,27); - add(label15); - actionSelectionBox.setBounds(430, 242,175,27); - add(actionSelectionBox); - - label14.setBounds(330, 280, 300, 27); - add(label14); - - } - - /** - * Populate GraphDBFields from Settings structure. - * @param settings The settings to load. - */ - public void populateFrom(final Settings settings) { - stateModelEnabledChkBox.setSelected(settings.get(ConfigTags.StateModelEnabled)); - stateModelWidgetStoreChkBox.setSelected(settings.get(ConfigTags.StateModelStoreWidgets)); - accessBridgeEnabledBox.setSelected(settings.get(ConfigTags.AccessBridgeEnabled)); - dataStoreTextfield.setText(settings.get(ConfigTags.DataStore)); - dataStoreServerTextfield.setText(settings.get(ConfigTags.DataStoreServer)); - dataStoreDirectoryField.setText(settings.get(ConfigTags.DataStoreDirectory)); - dataStoreDBTextfield.setText(settings.get(ConfigTags.DataStoreDB)); - dataStoreUserTextfield.setText(settings.get(ConfigTags.DataStoreUser)); - dataStorePasswordfield.setText(settings.get(ConfigTags.DataStorePassword)); - for (int i =0; i < dataStoreModeBox.getItemCount(); i++) { - if (dataStoreModeBox.getItemAt(i).equals(settings.get(ConfigTags.DataStoreMode))) { - dataStoreModeBox.setSelectedIndex(i); - break; - } - } - for (int i=0; i < dataStoreTypeBox.getItemCount(); i++) { - if (dataStoreTypeBox.getItemAt(i).equals(settings.get(ConfigTags.DataStoreType))) { - dataStoreTypeBox.setSelectedIndex(i); - } - } - // check if the fields should be enabled or not - components.forEach((component) -> component.setEnabled(stateModelEnabledChkBox.isSelected())); - checkDataType(); - checkAnalysisButtonActive(); - outputDir = settings.get(ConfigTags.OutputDir); - // check if the output directory has a trailing line separator - if (!outputDir.substring(outputDir.length() - 1).equals(File.separator)) { - outputDir += File.separator; - } - outputDir = outputDir + "graphs" + File.separator; - - // set the selected state management tags - if (settings.get(ConfigTags.AbstractStateAttributes) != null) { - List abstractStateAttributes = settings.get(ConfigTags.AbstractStateAttributes); - selectedStateManagementTags = abstractStateAttributes.stream().map(StateManagementTags::getTagFromSettingsString).filter(tag -> tag != null).toArray(Tag[]::new); - } - else { - selectedStateManagementTags = new Tag[0]; - } - - // for now, only two options, so we'll do this the quick and easy way, without creating a list model - String currentAlgorithm = settings.get(ConfigTags.ActionSelectionAlgorithm); - for (int i =0; i < actionSelectionBox.getItemCount(); i++) { - if (actionSelectionBox.getItemAt(i).equals("Random selection") && currentAlgorithm.equals("random")) { - actionSelectionBox.setSelectedIndex(i); - break; - } - if (actionSelectionBox.getItemAt(i).equals("Unvisited actions first") && currentAlgorithm.equals("unvisited")) { - actionSelectionBox.setSelectedIndex(i); - break; - } - } - - } - - /** - * Retrieve information from the GraphDB GUI. - * @param settings reference to the object where the settings will be stored. - */ - public void extractInformation(final Settings settings) { - settings.set(ConfigTags.StateModelEnabled, stateModelEnabledChkBox.isSelected()); - settings.set(ConfigTags.StateModelStoreWidgets, stateModelWidgetStoreChkBox.isSelected()); - settings.set(ConfigTags.DataStore, dataStoreTextfield.getText()); - settings.set(ConfigTags.DataStoreServer, dataStoreServerTextfield.getText()); - settings.set(ConfigTags.DataStoreDirectory, dataStoreDirectoryField.getText()); - settings.set(ConfigTags.DataStoreDB, dataStoreDBTextfield.getText()); - settings.set(ConfigTags.DataStoreUser, dataStoreUserTextfield.getText()); - settings.set(ConfigTags.DataStorePassword, getPassword()); - settings.set(ConfigTags.DataStoreMode, (String)dataStoreModeBox.getSelectedItem()); - settings.set(ConfigTags.DataStoreType, (String)dataStoreTypeBox.getSelectedItem()); - settings.set(ConfigTags.ResetDataStore, resetDatabaseCheckbox.isSelected()); - settings.set(ConfigTags.AccessBridgeEnabled, accessBridgeEnabledBox.isSelected()); - settings.set(ConfigTags.AbstractStateAttributes, Arrays.stream(selectedStateManagementTags).map(StateManagementTags::getSettingsStringFromTag).collect(Collectors.toList())); - switch ((String) actionSelectionBox.getSelectedItem()) { - case "Unvisited actions first": - settings.set(ConfigTags.ActionSelectionAlgorithm, "unvisited"); - break; - - default: - settings.set(ConfigTags.ActionSelectionAlgorithm, "random"); - } - } - - /** - * Convert password field to string. - * @return password as String. - */ - private String getPassword() { - StringBuilder result= new StringBuilder(); - for(char c : dataStorePasswordfield.getPassword()) { - result.append(c); - } - return result.toString(); - } - - // make sure the right text fields are enabled based on the selected data store type (remote or local) - private void checkDataType() { - dataStoreServerTextfield.setEnabled(dataStoreTypeBox.getSelectedItem().equals("remote") && stateModelEnabledChkBox.isSelected()); - dataStoreDirectoryField.setEnabled(dataStoreTypeBox.getSelectedItem().equals("plocal")); - dirButton.setEnabled(dataStoreTypeBox.getSelectedItem().equals("plocal")); - } - - // helper method to ensure that the state model enabled box is selected - private void checkAnalysisButtonActive() { - analysisButton.setEnabled(stateModelEnabledChkBox.isSelected()); - } - - // show a file dialog to choose the directory where the local install of OrientDB is located - private void chooseFileActionPerformed(ActionEvent evt) { - JFileChooser fd = new JFileChooser(); - fd.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - fd.setCurrentDirectory(new File(dataStoreDirectoryField.getText()).getParentFile()); - - if (fd.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String file = fd.getSelectedFile().getAbsolutePath(); - - // Set the text from settings in txtSutPath - dataStoreDirectoryField.setText(file); - } - } - - // this helper method will start a jetty integrated server and show the model listings page - private void openServer() { - try { - label14.setText(""); - // create a config object for the orientdb database connection info - Config config = new Config(); - config.setConnectionType((String)dataStoreTypeBox.getSelectedItem()); - config.setServer(dataStoreServerTextfield.getText()); - config.setDatabase(dataStoreDBTextfield.getText()); - config.setUser(dataStoreUserTextfield.getText()); - config.setPassword(getPassword()); - config.setDatabaseDirectory(dataStoreDirectoryField.getText()); - AnalysisManager analysisManager = new AnalysisManager(config, outputDir); - JettyServer jettyServer = new JettyServer(); - jettyServer.start(outputDir, analysisManager); - } catch (IOException e) { - // If the exception is because the server is already running, just catch and connect - if(e.getCause() != null && e.getCause().getMessage() != null && e.getCause().getMessage().contains("Address already in use")) { - System.out.println(e.getCause().getMessage()); - // Continue and try to open the browser to the running server - } else { - label14.setText("Please check your connection credentials."); - e.printStackTrace(); - // Something wrong with the database connection, return because we don't want to open the browser - return; - } - } catch (Exception e) { - // the plain Exception is coming from 3rd party code - label14.setText("Please check your connection credentials."); - e.printStackTrace(); - // Something wrong with the database connection, return because we don't want to open the browser - return; - } - - openBrowser(); - } - - private void openBrowser() { - try { - Desktop desktop = java.awt.Desktop.getDesktop(); - URI uri = new URI("http://localhost:8090/models"); - desktop.browse(uri); - } catch (IOException e) { - e.printStackTrace(); - } catch (URISyntaxException e) { - e.printStackTrace(); - } - } - - private void openStateTagSelection() { - stateTagsDialog = new AbstractStateSettings(allStateManagementTags, selectedStateManagementTags, CodingManager.getDefaultAbstractStateTags()); - stateTagsDialog.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - // tell the manager to shut down its connection - selectedStateManagementTags = stateTagsDialog.getCurrentlySelectedStateTags(); - } - }); - } - -} diff --git a/testar/src/org/testar/settingsdialog/dialog/TimingPanel.java b/testar/src/org/testar/settingsdialog/dialog/TimingPanel.java deleted file mode 100644 index 891c939f8..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/TimingPanel.java +++ /dev/null @@ -1,166 +0,0 @@ -/*************************************************************************************************** -* -* Copyright (c) 2013 - 2020 Universitat Politecnica de Valencia - www.upv.es -* Copyright (c) 2018 - 2020 Open Universiteit - www.ou.nl -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************************************/ - - -package org.testar.settingsdialog.dialog; - -import org.testar.monkey.ConfigTags; -import org.testar.monkey.Settings; -import org.testar.settingsdialog.SettingsPanel; - -import javax.swing.*; - -public class TimingPanel extends SettingsPanel { - - private static final long serialVersionUID = -5878966626046293031L; - - private JSpinner spnActionDuration; - private JSpinner spnActionWaitTime; - private JSpinner spnSutStartupTime; - private JSpinner spnMaxTime; - private JCheckBox checkUseRecordedTimes; - - public TimingPanel() { - setLayout(null); - - addTimingControls(); - addTimingLabels(); - } - - private void addTimingControls() { - spnActionDuration = new JSpinner(); - spnActionDuration.setBounds(143, 14, 100, 27); - spnActionDuration.setModel(new SpinnerNumberModel(0.0d, 0.0d, null, 0.1d)); - spnActionDuration.setToolTipText(ToolTipTexts.actionDurationTTT); - add(spnActionDuration); - - spnActionWaitTime = new JSpinner(); - spnActionWaitTime.setBounds(143, 52, 100, 27); - spnActionWaitTime.setModel(new SpinnerNumberModel(0.0d, 0.0d, null, 0.1d)); - spnActionWaitTime.setToolTipText(ToolTipTexts.actionWaitTimeTTT); - add(spnActionWaitTime); - - spnSutStartupTime = new JSpinner(); - spnSutStartupTime.setBounds(143, 90, 100, 27); - spnSutStartupTime.setModel(new SpinnerNumberModel(0.0d, 0.0d, null, 1.0d)); - spnSutStartupTime.setToolTipText(ToolTipTexts.sutStartupTimeTTT); - add(spnSutStartupTime); - - spnMaxTime = new JSpinner(); - spnMaxTime.setBounds(143, 128, 100, 31); - spnMaxTime.setModel(new SpinnerNumberModel(0.0d, 0.0d, null, 1.0d)); - spnMaxTime.setToolTipText(ToolTipTexts.maxTestTimeTTT); - add(spnMaxTime); - - checkUseRecordedTimes = new JCheckBox(); - checkUseRecordedTimes.setBounds(271, 177, 21, 21); - checkUseRecordedTimes.setToolTipText(ToolTipTexts.useRecordedTTT); - add(checkUseRecordedTimes); - } - - private void addTimingLabels() { - JLabel jLabel2 = new JLabel("Action Duration:"); - jLabel2.setBounds(10, 14, 130, 14); - jLabel2.setToolTipText(ToolTipTexts.actionDurationTTT); - add(jLabel2); - - JLabel jLabel3 = new JLabel("seconds"); - jLabel3.setBounds(256, 17, 52, 14); - jLabel3.setToolTipText(ToolTipTexts.actionDurationTTT); - add(jLabel3); - - - JLabel jLabel4 = new JLabel(); - jLabel4.setBounds(10, 52, 130, 14); - jLabel4.setText("Action Wait Time:"); - jLabel4.setToolTipText(ToolTipTexts.actionWaitTimeTTT); - add(jLabel4); - - JLabel jLabel5 = new JLabel("seconds"); - jLabel5.setBounds(256, 55, 52, 14); - jLabel5.setToolTipText(ToolTipTexts.actionWaitTimeTTT); - add(jLabel5); - - - JLabel jLabel7 = new JLabel("seconds"); - jLabel7.setBounds(256, 93, 52, 14); - jLabel7.setToolTipText(ToolTipTexts.sutStartupTimeTTT); - add(jLabel7); - - JLabel jLabel6 = new JLabel("SUT Startup Time:"); - jLabel6.setBounds(10, 90, 130, 14); - jLabel6.setToolTipText(ToolTipTexts.sutStartupTimeTTT); - add(jLabel6); - - - JLabel jLabel22 = new JLabel("Max. Test Time:"); - jLabel22.setBounds(10, 128, 130, 14); - jLabel22.setToolTipText(ToolTipTexts.maxTestTimeTTT); - add(jLabel22); - - JLabel jLabel23 = new JLabel("seconds"); - jLabel23.setBounds(256, 131, 52, 14); - jLabel23.setToolTipText(ToolTipTexts.maxTestTimeTTT); - add(jLabel23); - - JLabel jLabel24 = new JLabel("Use Recorded Action Timing during Replay:"); - jLabel24.setBounds(10, 177, 255, 14); - jLabel24.setToolTipText(ToolTipTexts.useRecordedTTT); - add(jLabel24); - } - - /** - * Populate Timing Fields from Settings structure. - * - * @param settings The settings to load. - */ - @Override - public void populateFrom(final Settings settings) { - checkUseRecordedTimes.setSelected(settings.get(ConfigTags.UseRecordedActionDurationAndWaitTimeDuringReplay)); - spnActionWaitTime.setValue(settings.get(ConfigTags.TimeToWaitAfterAction)); - spnActionDuration.setValue(settings.get(ConfigTags.ActionDuration)); - spnSutStartupTime.setValue(settings.get(ConfigTags.StartupTime)); - spnMaxTime.setValue(settings.get(ConfigTags.MaxTime)); - } - - /** - * Retrieve information from the Timing GUI. - * - * @param settings reference to the object where the settings will be stored. - */ - @Override - public void extractInformation(final Settings settings) { - settings.set(ConfigTags.UseRecordedActionDurationAndWaitTimeDuringReplay, checkUseRecordedTimes.isSelected()); - settings.set(ConfigTags.ActionDuration, (Double) spnActionDuration.getValue()); - settings.set(ConfigTags.TimeToWaitAfterAction, (Double) spnActionWaitTime.getValue()); - settings.set(ConfigTags.StartupTime, (Double) spnSutStartupTime.getValue()); - settings.set(ConfigTags.MaxTime, (Double) spnMaxTime.getValue()); - } -} diff --git a/testar/src/org/testar/settingsdialog/dialog/VCSPanel.java b/testar/src/org/testar/settingsdialog/dialog/VCSPanel.java deleted file mode 100644 index 487a7e5c7..000000000 --- a/testar/src/org/testar/settingsdialog/dialog/VCSPanel.java +++ /dev/null @@ -1,413 +0,0 @@ -package org.testar.settingsdialog.dialog; - -import org.eclipse.jgit.lib.ProgressMonitor; -import org.testar.monkey.Settings; -import org.testar.settingsdialog.SettingsPanel; -import org.testar.settingsdialog.codeanalysis.CodeAnalysisService; -import org.testar.settingsdialog.codeanalysis.CodeAnalysisServiceImpl; -import org.testar.settingsdialog.codeanalysis.RepositoryLanguage; -import org.testar.settingsdialog.codeanalysis.RepositoryLanguageComposition; -import org.testar.settingsdialog.vcs.GitCredentials; -import org.testar.settingsdialog.vcs.GitService; -import org.testar.settingsdialog.vcs.GitServiceImpl; - -import javax.swing.*; -import javax.swing.plaf.basic.BasicProgressBarUI; -import java.awt.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeSupport; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.nio.file.Path; -import java.util.Comparator; -import java.util.List; -import java.util.Random; -import java.util.stream.Collectors; - -import static javax.swing.GroupLayout.DEFAULT_SIZE; -import static javax.swing.GroupLayout.PREFERRED_SIZE; -import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; -import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED; - -public class VCSPanel extends SettingsPanel { - - private JTextField gitRepositoryUrlTextField; - private JTextField gitUsernameTextField; - private JPasswordField gitPasswordField; - private JCheckBox authorizationRequiredCheckBox; - private JLabel gitRepositoryUrlLabel; - private JLabel gitUsernameLabel; - private JLabel gitPasswordLabel; - private JLabel authorizationRequiredLabel; - private JButton cloneButton; - private JLabel cloneProcessingLabel; - private JProgressBar cloneProcessingProgressBar; - private JLabel cloneTaskLabel; - private final JProgressBar[] languageContentProgressBars = new JProgressBar[LANGUAGES_TO_DISPLAY]; - private final JLabel[] languageContentLabels = new JLabel[LANGUAGES_TO_DISPLAY]; - private JButton fullScanningReportButton; - private final static int LANGUAGES_TO_DISPLAY = 3; - private final static int LANGUAGE_CONTENT_BAR_MIN = 0; - private final static int LANGUAGE_CONTENT_BAR_MAX = 100; - private final static int LANGUAGE_CONTENT_SCALE = 0; - private final static String GIT_URL_LABEL = "Repository URL"; - private final static String GIT_USERNAME_LABEL = "Username"; - private final static String GIT_PASSWORD_LABEL = "Password"; - private final static String AUTHORIZATION_REQUIRED_LABEL = "Authorization required"; - private final static String CLONE_BUTTON = "Clone"; - private final static String CLONE_ERROR_TITLE = "Clone error"; - private final static String CLONE_ERROR_MESSAGE = "Something went wrong, repository wasn't cloned cloned. Check whether the repository already exists locally or credentials are valid."; - private final static String CLONE_SUCCESS_TITLE = "Clone success"; - private final static String CLONE_SUCCESS_MESSAGE = "Repository cloned successfully"; - private final static String CLONE_PROCESSING_LABEL = "Cloning project..."; - private final static String FULL_REPORT_BUTTON = "Full report"; - private final static String CLONING_PROPERTY = "cloning_property"; - - - private PropertyChangeSupport propertyChangeSupport; - - private GitService gitService; - private CodeAnalysisService codeAnalysisService; - - private RepositoryLanguageComposition repositoryComposition; - - public VCSPanel() { - gitService = new GitServiceImpl(); - codeAnalysisService = new CodeAnalysisServiceImpl(); - propertyChangeSupport = new PropertyChangeSupport(this); - propertyChangeSupport.addPropertyChangeListener(this::cloneFinished); - initGitRepositoryUrlSection(); - initGitUsernameSection(); - initGitPasswordSection(); - initAuthorizationRequiredSection(); - initCloneSection(); - initLanguagesSection(); - } - - private void cloneFinished(PropertyChangeEvent evt) { - Object cloneSuccessful = evt.getNewValue(); - if (cloneSuccessful != null) { - showCloneSuccessDialog(); - } else { - showCloneErrorDialog(); - } - cloneButton.setEnabled(true); - toggleCloneProcessingVisibility(false); - } - - private void showCloneErrorDialog() { - JOptionPane.showMessageDialog(this, - CLONE_ERROR_MESSAGE, - CLONE_ERROR_TITLE, - JOptionPane.ERROR_MESSAGE); - } - - private void showCloneSuccessDialog() { - JOptionPane.showMessageDialog(this, - CLONE_SUCCESS_MESSAGE, - CLONE_SUCCESS_TITLE, - JOptionPane.INFORMATION_MESSAGE); - } - - private void initGitRepositoryUrlSection() { - gitRepositoryUrlLabel = new JLabel(GIT_URL_LABEL); - gitRepositoryUrlTextField = new JTextField(); - } - - private void initGitUsernameSection() { - gitUsernameLabel = new JLabel(GIT_USERNAME_LABEL); - gitUsernameTextField = new JTextField(); - - } - - private void initGitPasswordSection() { - gitPasswordLabel = new JLabel(GIT_PASSWORD_LABEL); - gitPasswordField = new JPasswordField(); - } - - private void initAuthorizationRequiredSection() { - authorizationRequiredLabel = new JLabel(AUTHORIZATION_REQUIRED_LABEL); - authorizationRequiredCheckBox = new JCheckBox(); - authorizationRequiredCheckBox.setSelected(true); - authorizationRequiredCheckBox.addItemListener(e -> setAuthorizationFieldsEnabled(authorizationRequiredCheckBox.isSelected())); - } - - private void setAuthorizationFieldsEnabled(boolean enabled) { - gitUsernameTextField.setEnabled(enabled); - gitPasswordField.setEnabled(enabled); - } - - private void initCloneSection() { - cloneButton = new JButton(CLONE_BUTTON); - cloneButton.addActionListener(e -> { - cloneButton.setEnabled(false); - toggleLanguageSectionVisibility(false); - if (authorizationRequiredCheckBox.isSelected()) { - cloneRepositoryWithAuth(); - } else { - cloneRepository(); - } - }); - cloneProcessingLabel = new JLabel(CLONE_PROCESSING_LABEL); - cloneProcessingProgressBar = new JProgressBar(); - cloneTaskLabel = new JLabel(); - toggleCloneProcessingVisibility(false); - } - - private void toggleLanguageSectionVisibility(boolean visible) { - for (int i = 0; i < LANGUAGES_TO_DISPLAY; i++) { - toggleLanguageVisibility(visible, i); - } - this.fullScanningReportButton.setVisible(visible); - } - - private void toggleLanguageVisibility(boolean visible, int index) { - languageContentProgressBars[index].setVisible(visible); - languageContentLabels[index].setVisible(visible); - } - - private void cloneRepositoryWithAuth() { - toggleCloneProcessingVisibility(true); - new Thread(() -> { - GitCredentials credentials = new GitCredentials(gitUsernameTextField.getText(), new String(gitPasswordField.getPassword())); - Path repositoryPath = gitService.cloneRepository(gitRepositoryUrlTextField.getText(), credentials, new ProgressBarMonitor()); - scanRepository(repositoryPath); - toggleCloneProcessingVisibility(false); - viewRepositoryComposition(); - propertyChangeSupport.firePropertyChange(CLONING_PROPERTY, null, repositoryPath); - }).start(); - } - - private void toggleCloneProcessingVisibility(boolean visible) { - cloneProcessingLabel.setVisible(visible); - cloneProcessingProgressBar.setVisible(visible); - cloneTaskLabel.setVisible(visible); - } - - private void scanRepository(Path repositoryPath) { - cloneTaskLabel.setText("Scanning languages..."); - this.repositoryComposition = codeAnalysisService.scanRepository(repositoryPath); - cloneTaskLabel.setText(""); - } - - private void viewRepositoryComposition() { - List repositoryLanguages = repositoryComposition.getRepositoryLanguages() - .stream() - .sorted(Comparator.comparing(RepositoryLanguage::getLinesOfCode, Comparator.reverseOrder())) - .collect(Collectors.toList()); - for (int i = 0; (i < LANGUAGES_TO_DISPLAY) && (i < repositoryComposition.getRepositoryLanguages().size()); i++) { - setLanguageValue(repositoryLanguages.get(i), i); - } - if (repositoryComposition.getRepositoryLanguages().size() > LANGUAGES_TO_DISPLAY) { - fullScanningReportButton.setVisible(true); - } - } - - private void setLanguageValue(RepositoryLanguage repositoryLanguage, int index) { - toggleLanguageVisibility(true, index); - styleLanguageProgressBar(languageContentProgressBars[index]); - languageContentProgressBars[index].setValue(repositoryLanguage.getPercentage() - .multiply(new BigDecimal(Math.pow(10, LANGUAGE_CONTENT_SCALE))) - .intValue()); - languageContentLabels[index].setText(repositoryLanguage.getPercentage().setScale(LANGUAGE_CONTENT_SCALE, RoundingMode.HALF_UP).toString() + "% " + repositoryLanguage.getSupportedLanguage().getName()); - } - - private void styleLanguageProgressBar(JProgressBar progressBar) { - Random colorGen = new Random(); - progressBar.setUI(new LanguageProgressBarUI()); - Color foregroundColor = new Color(colorGen.nextInt(255), colorGen.nextInt(255), colorGen.nextInt(255)); - progressBar.setForeground(foregroundColor); - progressBar.setBackground(Color.LIGHT_GRAY); - } - - private void cloneRepository() { - toggleCloneProcessingVisibility(true); - new Thread(() -> { - Path repositoryPath = gitService.cloneRepository(gitRepositoryUrlTextField.getText(), new ProgressBarMonitor()); - scanRepository(repositoryPath); - toggleCloneProcessingVisibility(false); - viewRepositoryComposition(); - propertyChangeSupport.firePropertyChange(CLONING_PROPERTY, null, repositoryPath); - }).start(); - } - - private void initLanguagesSection() { - for (int i = 0; i < LANGUAGES_TO_DISPLAY; i++) { - languageContentLabels[i] = new JLabel(); - languageContentProgressBars[i] = new JProgressBar(LANGUAGE_CONTENT_BAR_MIN, LANGUAGE_CONTENT_BAR_MAX); - } - this.fullScanningReportButton = new JButton(FULL_REPORT_BUTTON); - this.fullScanningReportButton.addActionListener((event) -> { - viewFullReport(); - }); - toggleLanguageSectionVisibility(false); - } - - private void viewFullReport() { - new ScanningReportDialog(repositoryComposition); - } - - /** - * Populate the fields from Settings structure. - * - * @param settings The settings to load. - */ - @Override - public void populateFrom(Settings settings) { - GroupLayout groupLayout = new GroupLayout(this); - this.setLayout(groupLayout); - groupLayout.setHorizontalGroup( - groupLayout.createSequentialGroup() - .addContainerGap(18, 20) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false) - .addGroup(groupLayout.createSequentialGroup() - .addComponent(gitRepositoryUrlLabel, PREFERRED_SIZE, 120, PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(gitRepositoryUrlTextField, PREFERRED_SIZE, 346, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addComponent(authorizationRequiredLabel, PREFERRED_SIZE, 120, PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(authorizationRequiredCheckBox, PREFERRED_SIZE, 346, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addComponent(gitUsernameLabel, PREFERRED_SIZE, 120, PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(gitUsernameTextField, PREFERRED_SIZE, 346, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addComponent(gitPasswordLabel, PREFERRED_SIZE, 120, PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(gitPasswordField, PREFERRED_SIZE, 346, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(cloneButton, PREFERRED_SIZE, 65, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(cloneProcessingLabel, PREFERRED_SIZE, 120, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(cloneProcessingProgressBar, PREFERRED_SIZE, 200, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(cloneTaskLabel, PREFERRED_SIZE, 200, PREFERRED_SIZE)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(languageContentProgressBars[0], PREFERRED_SIZE, 200, PREFERRED_SIZE) - .addGap(PREFERRED_SIZE, 10, PREFERRED_SIZE) - .addComponent(languageContentLabels[0], 20, 60, 200)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(languageContentProgressBars[1], PREFERRED_SIZE, 200, PREFERRED_SIZE) - .addGap(PREFERRED_SIZE, 10, PREFERRED_SIZE) - .addComponent(languageContentLabels[1], 20, 60, 200)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(languageContentProgressBars[2], PREFERRED_SIZE, 200, PREFERRED_SIZE) - .addGap(PREFERRED_SIZE, 10, PREFERRED_SIZE) - .addComponent(languageContentLabels[2], 20, 60, 200)) - .addGroup(groupLayout.createSequentialGroup() - .addGap(PREFERRED_SIZE, 138, PREFERRED_SIZE) - .addComponent(fullScanningReportButton)) - )); - - groupLayout.setVerticalGroup( - groupLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(groupLayout.createSequentialGroup() - .addContainerGap(18, 20) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(gitRepositoryUrlTextField, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) - .addComponent(gitRepositoryUrlLabel)) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(authorizationRequiredCheckBox, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) - .addComponent(authorizationRequiredLabel)) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(gitUsernameTextField, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) - .addComponent(gitUsernameLabel)) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(gitPasswordField, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE) - .addComponent(gitPasswordLabel)) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(cloneButton, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(cloneProcessingLabel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(cloneProcessingProgressBar, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(cloneTaskLabel, PREFERRED_SIZE, DEFAULT_SIZE, PREFERRED_SIZE)) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(languageContentProgressBars[0]) - .addComponent(languageContentLabels[0])) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(languageContentProgressBars[1]) - .addComponent(languageContentLabels[1])) - .addPreferredGap(RELATED) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(languageContentProgressBars[2]) - .addComponent(languageContentLabels[2])) - .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(fullScanningReportButton)) - .addPreferredGap(UNRELATED) - )); - } - - /** - * Retrieve information from the GUI. - * - * @param settings reference to the object where the settings will be stored. - */ - @Override - public void extractInformation(Settings settings) { - // TODO: Add information saving - } - - private class ProgressBarMonitor implements ProgressMonitor { - - @Override - public void start(int totalTasks) { - } - - @Override - public void beginTask(String title, int totalWork) { - cloneProcessingProgressBar.setMinimum(0); - cloneProcessingProgressBar.setMaximum(totalWork); - cloneProcessingProgressBar.setValue(0); - cloneTaskLabel.setText(title); - } - - @Override - public void update(int completed) { - cloneProcessingProgressBar.setValue(cloneProcessingProgressBar.getValue() + completed); - } - - @Override - public void endTask() { - cloneProcessingProgressBar.setValue(cloneProcessingProgressBar.getMaximum()); - cloneTaskLabel.setText(""); - } - - @Override - public boolean isCancelled() { - return false; - } - } - - class LanguageProgressBarUI extends BasicProgressBarUI { - Rectangle r = new Rectangle(); - - @Override - protected void paintIndeterminate(Graphics g, JComponent c) { - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - r = getBox(r); - g.setColor(progressBar.getForeground()); - g.fillOval(r.x, r.y, r.width, r.height); - } - } -} diff --git a/testar/src/org/testar/settingsdialog/vcs/GitService.java b/testar/src/org/testar/settingsdialog/vcs/GitService.java index c84fbf761..36c8ff3e2 100644 --- a/testar/src/org/testar/settingsdialog/vcs/GitService.java +++ b/testar/src/org/testar/settingsdialog/vcs/GitService.java @@ -7,7 +7,7 @@ public interface GitService { - Path cloneRepository(String repositoryUrl, ProgressMonitor progressMonitor); + Path cloneRepository(String repositoryUrl, ProgressMonitor progressMonitor, String branchName); - Path cloneRepository(String repositoryUrl, GitCredentials gitCredentials, ProgressMonitor progressMonitor); + Path cloneRepository(String repositoryUrl, GitCredentials gitCredentials, ProgressMonitor progressMonitor, String branchName); } diff --git a/testar/src/org/testar/settingsdialog/vcs/GitServiceImpl.java b/testar/src/org/testar/settingsdialog/vcs/GitServiceImpl.java index dbaab0dcd..9a4766428 100644 --- a/testar/src/org/testar/settingsdialog/vcs/GitServiceImpl.java +++ b/testar/src/org/testar/settingsdialog/vcs/GitServiceImpl.java @@ -1,5 +1,6 @@ package org.testar.settingsdialog.vcs; +import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; @@ -15,14 +16,19 @@ public class GitServiceImpl implements GitService { public static final String LOCAL_REPOSITORIES_PATH = "cloned"; @Override - public Path cloneRepository(String repositoryUrl, ProgressMonitor progressMonitor) { + public Path cloneRepository(String repositoryUrl, ProgressMonitor progressMonitor, String branchName) { try { File repositoryDirectory = prepareRepositoryDirectory(repositoryUrl); - Git.cloneRepository() + CloneCommand cloneCommand = Git.cloneRepository() .setURI(repositoryUrl) .setDirectory(repositoryDirectory) - .setProgressMonitor(progressMonitor) - .call(); + .setProgressMonitor(progressMonitor); + + if (branchName != null && branchName.length() > 0) { + cloneCommand = cloneCommand.setBranch(branchName); + } + + cloneCommand.call(); return repositoryDirectory.toPath(); } catch (GitAPIException | JGitInternalException e) { e.printStackTrace(); @@ -32,15 +38,20 @@ public Path cloneRepository(String repositoryUrl, ProgressMonitor progressMonito } @Override - public Path cloneRepository(String repositoryUrl, GitCredentials gitCredentials, ProgressMonitor progressMonitor) { + public Path cloneRepository(String repositoryUrl, GitCredentials gitCredentials, ProgressMonitor progressMonitor, String branchName) { try { File repositoryDirectory = prepareRepositoryDirectory(repositoryUrl); - Git.cloneRepository() + CloneCommand cloneCommand =Git.cloneRepository() .setURI(repositoryUrl) .setDirectory(repositoryDirectory) .setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitCredentials.getUsername(), gitCredentials.getPassword())) - .setProgressMonitor(progressMonitor) - .call(); + .setProgressMonitor(progressMonitor); + + if (branchName != null && branchName.length() > 0) { + cloneCommand = cloneCommand.setBranch(branchName); + } + + cloneCommand.call(); return repositoryDirectory.toPath(); } catch (GitAPIException | JGitInternalException e) { diff --git a/testar/src/org/testar/statemodel/QueueVisualizer.java b/testar/src/org/testar/statemodel/QueueVisualizer.java deleted file mode 100644 index ca8c5fe50..000000000 --- a/testar/src/org/testar/statemodel/QueueVisualizer.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.testar.statemodel; - -import javax.swing.*; -import java.awt.*; - -public class QueueVisualizer extends JDialog { - - private Label msg; - - public QueueVisualizer(String title) { - super((JFrame)null, title, false); - setLocationRelativeTo(null); - this.setType(Type.POPUP); - this.setUndecorated(true); - msg = new Label(title); - msg.setBackground(Color.BLACK); - msg.setForeground(Color.WHITE); - this.add(msg); - int dimW = (title.length() + 1) * 12; - this.setSize(new Dimension(dimW > 512 ? 512 : dimW, 32)); - this.setEnabled(false); - this.setOpacity(0.75f); - this.setVisible(true); - } - - public void updateMessage(String message) { - msg.setText(message); - msg.repaint(); - } - - public void stop() { - this.setVisible(false); - this.dispose(); - } -} diff --git a/testar/src/org/testar/statemodel/persistence/QueueManager.java b/testar/src/org/testar/statemodel/persistence/QueueManager.java index fcc046b23..584cbeb7d 100644 --- a/testar/src/org/testar/statemodel/persistence/QueueManager.java +++ b/testar/src/org/testar/statemodel/persistence/QueueManager.java @@ -57,18 +57,19 @@ private void processRequest(Runnable runnable, Persistable persistable) { @Override public void shutdown() { - if (!queue.isEmpty()) { - int nrOfItemsProcessed = 0; - int totalNrOfItems = queue.size(); - QueueVisualizer visualizer = new QueueVisualizer("Processing persistence queue"); - visualizer.updateMessage("Processing persistence queue : " + nrOfItemsProcessed + " / " + totalNrOfItems + " processed"); - while (!queue.isEmpty()) { - queue.remove().run(); - nrOfItemsProcessed++; - visualizer.updateMessage("Processing persistence queue : " + nrOfItemsProcessed + " / " + totalNrOfItems + " processed"); - } - visualizer.stop(); - } + // TODO: port queue visualizer +// if (!queue.isEmpty()) { +// int nrOfItemsProcessed = 0; +// int totalNrOfItems = queue.size(); +// QueueVisualizer visualizer = new QueueVisualizer("Processing persistence queue"); +// visualizer.updateMessage("Processing persistence queue : " + nrOfItemsProcessed + " / " + totalNrOfItems + " processed"); +// while (!queue.isEmpty()) { +// queue.remove().run(); +// nrOfItemsProcessed++; +// visualizer.updateMessage("Processing persistence queue : " + nrOfItemsProcessed + " / " + totalNrOfItems + " processed"); +// } +// visualizer.stop(); +// } delegateManager.shutdown(); } diff --git a/testar/test/org/fruit/monkey/vcs/GitServiceImplTest.java b/testar/test/org/fruit/monkey/vcs/GitServiceImplTest.java index 01b81abaf..b7098dad3 100644 --- a/testar/test/org/fruit/monkey/vcs/GitServiceImplTest.java +++ b/testar/test/org/fruit/monkey/vcs/GitServiceImplTest.java @@ -53,8 +53,8 @@ public static void tearDown() throws IOException { @Test public void cloneRepository() { - Path resultSuccess = gitService.cloneRepository(PUBLIC_REPOSITORY_URL, new TextProgressMonitor()); - Path resultDirectoryExistsError = gitService.cloneRepository(PUBLIC_REPOSITORY_URL, new TextProgressMonitor()); + Path resultSuccess = gitService.cloneRepository(PUBLIC_REPOSITORY_URL, new TextProgressMonitor(), null); + Path resultDirectoryExistsError = gitService.cloneRepository(PUBLIC_REPOSITORY_URL, new TextProgressMonitor(), null); assertNotNull(resultSuccess); assertNull(resultDirectoryExistsError); } @@ -64,9 +64,9 @@ public void cloneRepositoryWithAuth() { GitCredentials wrongCredentials = new GitCredentials(PRIVATE_REPOSITORY_USERNAME, PRIVATE_REPOSITORY_WRONG_PASSWORD); GitCredentials correctCredentials = new GitCredentials(PRIVATE_REPOSITORY_USERNAME, PRIVATE_REPOSITORY_CORRECT_PASSWORD); - Path resultAuthError = gitService.cloneRepository(PRIVATE_REPOSITORY_URL, wrongCredentials, new TextProgressMonitor()); - Path resultAuthSuccess = gitService.cloneRepository(PRIVATE_REPOSITORY_URL, correctCredentials, new TextProgressMonitor()); - Path resultDirectoryExistsError = gitService.cloneRepository(PRIVATE_REPOSITORY_URL, correctCredentials, new TextProgressMonitor()); + Path resultAuthError = gitService.cloneRepository(PRIVATE_REPOSITORY_URL, wrongCredentials, new TextProgressMonitor(), null); + Path resultAuthSuccess = gitService.cloneRepository(PRIVATE_REPOSITORY_URL, correctCredentials, new TextProgressMonitor(), null); + Path resultDirectoryExistsError = gitService.cloneRepository(PRIVATE_REPOSITORY_URL, correctCredentials, new TextProgressMonitor(), null); assertNull(resultAuthError); assertNotNull(resultAuthSuccess);