Merge changes Ibde48bff,I25ee1514,If386e833 into stable-3.5

* changes:
  show task name in case of bad applicability query
  rename 'untrusted user' to 'non-secret user' for docker tests
  move docker tests data creation to 'create-one-time-test-data.sh'
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
index d9d4039..5affd56 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
@@ -174,7 +174,12 @@
           attribute.evaluationMilliSeconds = millis();
         }
 
-        boolean applicable = node.match(task.applicable);
+        boolean applicable;
+        try {
+          applicable = node.match(task.applicable);
+        } catch (QueryParseException e) {
+          return Optional.of(invalid());
+        }
         if (!task.isVisible) {
           if (!node.isTrusted() || (!applicable && !options.onlyApplicable)) {
             return Optional.of(unknown());
@@ -218,12 +223,20 @@
             }
           }
         }
-      } catch (IOException | QueryParseException | RuntimeException e) {
+      } catch (IOException | RuntimeException e) {
         return Optional.of(invalid()); // bad applicability query
       }
       return Optional.empty();
     }
 
+    protected TaskAttribute invalid() {
+      TaskAttribute invalid = TaskAttributeFactory.invalid();
+      if (task.isVisible) {
+        invalid.name = task.name();
+      }
+      return invalid;
+    }
+
     public void addStatistics(TaskAttribute.Statistics statistics) {
       if (statistics != null) {
         statistics.isApplicableRefreshRequired = node.properties.isApplicableRefreshRequired();
@@ -316,7 +329,7 @@
       for (Node subNode :
           options.onlyApplicable ? node.getApplicableSubNodes() : node.getSubNodes()) {
         if (subNode instanceof Node.Invalid) {
-          subTasks.add(invalid());
+          subTasks.add(TaskAttributeFactory.invalid());
         } else {
           new AttributeFactory(subNode).create().ifPresent(t -> subTasks.add(t));
         }
diff --git a/src/main/resources/Documentation/test/preview.md b/src/main/resources/Documentation/test/preview.md
index 502ade2..ec5967f 100644
--- a/src/main/resources/Documentation/test/preview.md
+++ b/src/main/resources/Documentation/test/preview.md
@@ -114,6 +114,10 @@
          ]
       },
       {
+         "name" : "Bad APPLICABLE query",
+         "status" : "INVALID"
+      },
+      {
          "applicable" : false,
          "hasPass" : true,
          "name" : "NA Bad PASS query",
@@ -316,28 +320,28 @@
    "status" : "WAITING",
    "subTasks" : [
       {
-         "applicable" : true,                              # Only Test Suite: !untrusted
-         "hasPass" : true,                                 # Only Test Suite: !untrusted
-         "name" : "userfile task/special.config PASS",     # Only Test Suite: !untrusted
-         "status" : "PASS"                                 # Only Test Suite: !untrusted
-         "name" : "UNKNOWN",                               # Only Test Suite: untrusted
-         "status" : "UNKNOWN"                              # Only Test Suite: untrusted
+         "applicable" : true,                              # Only Test Suite: secret
+         "hasPass" : true,                                 # Only Test Suite: secret
+         "name" : "userfile task/special.config PASS",     # Only Test Suite: secret
+         "status" : "PASS"                                 # Only Test Suite: secret
+         "name" : "UNKNOWN",                               # Only Test Suite: !secret
+         "status" : "UNKNOWN"                              # Only Test Suite: !secret
       },
       {
-         "applicable" : true,                              # Only Test Suite: !untrusted
-         "hasPass" : true,                                 # Only Test Suite: !untrusted
-         "name" : "userfile task/special.config FAIL",     # Only Test Suite: !untrusted
-         "status" : "FAIL"                                 # Only Test Suite: !untrusted
-         "name" : "UNKNOWN",                               # Only Test Suite: untrusted
-         "status" : "UNKNOWN"                              # Only Test Suite: untrusted
+         "applicable" : true,                              # Only Test Suite: secret
+         "hasPass" : true,                                 # Only Test Suite: secret
+         "name" : "userfile task/special.config FAIL",     # Only Test Suite: secret
+         "status" : "FAIL"                                 # Only Test Suite: secret
+         "name" : "UNKNOWN",                               # Only Test Suite: !secret
+         "status" : "UNKNOWN"                              # Only Test Suite: !secret
       },
       {
-         "applicable" : true,                              # Only Test Suite: !untrusted
-         "hasPass" : true,                                 # Only Test Suite: !untrusted
-         "name" : "file task/common.config Preload PASS",  # Only Test Suite: !untrusted
-         "status" : "PASS"                                 # Only Test Suite: !untrusted
-         "name" : "UNKNOWN",                               # Only Test Suite: untrusted
-         "status" : "UNKNOWN"                              # Only Test Suite: untrusted
+         "applicable" : true,                              # Only Test Suite: secret
+         "hasPass" : true,                                 # Only Test Suite: secret
+         "name" : "file task/common.config Preload PASS",  # Only Test Suite: secret
+         "status" : "PASS"                                 # Only Test Suite: secret
+         "name" : "UNKNOWN",                               # Only Test Suite: !secret
+         "status" : "UNKNOWN"                              # Only Test Suite: !secret
       }
    ]
 }
@@ -470,6 +474,10 @@
          ]
       },
       {
+         "name" : "Bad APPLICABLE query",
+         "status" : "INVALID"
+      },
+      {
          "applicable" : false,
          "hasPass" : true,
          "name" : "NA Bad PASS query",
diff --git a/src/main/resources/Documentation/test/task_states.md b/src/main/resources/Documentation/test/task_states.md
index c5881c6..286af97 100644
--- a/src/main/resources/Documentation/test/task_states.md
+++ b/src/main/resources/Documentation/test/task_states.md
@@ -2278,6 +2278,11 @@
          ]
       },
       {
+         "name" : "Bad APPLICABLE query",    # Only Test Suite: visible
+         "name" : "UNKNOWN",                 # Only Test Suite: !visible
+         "status" : "INVALID"
+      },
+      {
          "applicable" : false,
          "hasPass" : true,
          "name" : "NA Bad PASS query",
@@ -2569,6 +2574,11 @@
          ]
       },
       {
+         "name" : "Bad APPLICABLE query",    # Only Test Suite: visible
+         "name" : "UNKNOWN",                 # Only Test Suite: !visible
+         "status" : "INVALID"
+      },
+      {
          "applicable" : false,
          "hasPass" : true,
          "name" : "NA Bad PASS query",
@@ -2769,6 +2779,10 @@
   pass = True
   subtask =
 
+[task "Bad APPLICABLE query"]
+  applicable = bad:query
+  fail = True
+
 [task "NA Bad PASS query"]
   applicable = NOT is:open # Assumes test query is "is:open"
   fail = True
diff --git a/test/check_task_statuses.sh b/test/check_task_statuses.sh
index 9fb939f..1880432 100755
--- a/test/check_task_statuses.sh
+++ b/test/check_task_statuses.sh
@@ -315,12 +315,15 @@
 usage() { # [error_message]
     cat <<-EOF
 Usage:
-    "$MYPROG" --server <gerrit_host> --untrusted-user <untrusted user>
+    "$MYPROG" --server <gerrit_host> --non-secret-user <non-secret user>
+    --untrusted-user <untrusted user>
 
     --help|-h                     help text
     --server|-s                   gerrit host
-    --untrusted-user              user who don't have permission
+    --non-secret-user             user who don't have permission
                                   to view other user refs.
+    --untrusted-user              user who doesn't have permission
+                                  to view refs/meta/config ref on All-Projects repo
 EOF
 
     [ -n "$1" ] && { echo "Error: $1" ; exit 1 ; }
@@ -354,6 +357,7 @@
     case "$1" in
         --help|-h)                usage ;;
         --server|-s)              shift ; SERVER=$1 ;;
+        --non-secret-user)        shift ; NON_SECRET_USER=$1 ;;
         --untrusted-user)         shift ; UNTRUSTED_USER=$1 ;;
         *)                        usage "invalid argument $1" ;;
     esac
@@ -361,6 +365,7 @@
 done
 
 [ -z "$SERVER" ] && usage "You must specify --server"
+[ -z "$NON_SECRET_USER" ] && usage "You must specify --non-secret-user"
 [ -z "$UNTRUSTED_USER" ] && usage "You must specify --untrusted-user"
 
 
@@ -423,27 +428,36 @@
         "NEW" \
         "")
 
-no_all_json=$(echo "$all_pjson" | remove_suites all)
-no_all2_json=$(echo "$all2_pjson" | remove_suites all)
+no_all_visible_json=$(echo "$all_pjson" | remove_suites "all" "!visible")
+no_all_no_visible_json=$(echo "$all_pjson" | remove_suites "all" "visible")
+no_all_visible2_json=$(echo "$all2_pjson" | remove_suites "all" "!visible")
+no_all_no_visible2_json=$(echo "$all2_pjson" | remove_suites "all" "visible")
 
-echo "$no_all_json" | strip_non_applicable | \
+echo "$no_all_visible_json" | strip_non_applicable | \
     grep -v "\"applicable\" :" > "$EXPECTED".applicable
-echo "$no_all2_json" | strip_non_applicable | \
+
+echo "$no_all_no_visible_json" | strip_non_applicable | \
+    grep -v "\"applicable\" :" > "$EXPECTED".applicable-visibility
+
+echo "$no_all_visible2_json" | strip_non_applicable | \
     grep -v "\"applicable\" :" > "$EXPECTED".applicable2
 
-echo "$all_pjson" | remove_not_suite all | ensure json_pp > "$EXPECTED".all
+echo "$no_all_no_visible2_json" | strip_non_applicable | \
+    grep -v "\"applicable\" :" > "$EXPECTED".applicable-visibility2
 
-echo "$no_all_json" | strip_non_invalid > "$EXPECTED".invalid
+echo "$all_pjson" | remove_suites "!all" "!visible" | ensure json_pp > "$EXPECTED".all
+
+echo "$no_all_visible_json" | strip_non_invalid > "$EXPECTED".invalid
 
 strip_non_invalid < "$EXPECTED".applicable > "$EXPECTED".invalid-applicable
 
 
 preview_pjson=$(testdoc_2_pjson < "$DOC_PREVIEW" | replace_default_changes)
-echo "$preview_pjson" | remove_suites "invalid" "!untrusted" | \
-    ensure json_pp > "$EXPECTED".preview-untrusted
-echo "$preview_pjson" | remove_suites "invalid" "untrusted" | \
+echo "$preview_pjson" | remove_suites "invalid" "secret" | \
+    ensure json_pp > "$EXPECTED".preview-non-secret
+echo "$preview_pjson" | remove_suites "invalid" "!secret" | \
     ensure json_pp > "$EXPECTED".preview-admin
-echo "$preview_pjson" | remove_suites "!untrusted" "!invalid" | \
+echo "$preview_pjson" | remove_suites "secret" "!invalid" | \
     strip_non_invalid > "$EXPECTED".preview-invalid
 
 testdoc_2_cfg < "$DOC_PREVIEW" | replace_user > "$ROOT_CFG"
@@ -454,6 +468,7 @@
 RESULT=0
 query="(change:$change3_number OR change:$change4_number) status:open"
 test_2generated applicable --task--applicable "$query"
+test_2generated applicable-visibility -l "$UNTRUSTED_USER" --task--applicable "$query"
 test_generated all --task--all "$query"
 
 test_generated invalid --task--invalid "$query"
@@ -461,7 +476,7 @@
 
 ROOTS=$PREVIEW_ROOTS
 test_generated preview-admin --task--preview "$cnum,1" --task--all "$query"
-test_generated preview-untrusted -l "$UNTRUSTED_USER" --task--preview "$cnum,1" --task--all "$query"
+test_generated preview-non-secret -l "$NON_SECRET_USER" --task--preview "$cnum,1" --task--all "$query"
 test_generated preview-invalid --task--preview "$cnum,1" --task--invalid "$query"
 
 exit $RESULT
diff --git a/test/docker/run_tests/create-one-time-test-data.sh b/test/docker/run_tests/create-one-time-test-data.sh
new file mode 100755
index 0000000..9d9fcbd
--- /dev/null
+++ b/test/docker/run_tests/create-one-time-test-data.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+die() { echo -e "\nERROR:" "$@" ; kill $$ ; exit 1 ; } # error_message
+
+q() { "$@" > /dev/null 2>&1 ; } # cmd [args...]  # quiet a command
+
+gssh() { ssh -x -p "$SSH_PORT" "$GERRIT_HOST" gerrit "$@" ; } # run a gerrit ssh command
+
+create_test_users_and_group() {
+    echo "Creating test users and group ..."
+    gssh create-account "$NON_SECRET_USER" --full-name "$NON_SECRET_USER" \
+           --email "$NON_SECRET_USER"@example.com --ssh-key - < ~/.ssh/id_rsa.pub
+
+    gssh create-account "$UNTRUSTED_USER" --full-name "$UNTRUSTED_USER" \
+        --email "$UNTRUSTED_USER"@example.com --ssh-key - < ~/.ssh/id_rsa.pub
+
+    gssh create-group "Visible-All-Projects-Config" --member "$NON_SECRET_USER"
+}
+
+setup_all_projects_repo() {
+    echo "Updating All-Projects repo ..."
+
+    local uuid=$(gssh ls-groups -v | awk '-F\t' '$1 == "Visible-All-Projects-Config" {print $2}')
+    ( cd "$WORKSPACE"
+      q git clone ssh://"$GERRIT_HOST":"$SSH_PORT"/All-Projects allProjects
+      cd allProjects
+      q git fetch origin refs/meta/config ; q git checkout FETCH_HEAD
+      echo -e "$uuid\tVisible-All-Projects-Config" >> groups
+      git config -f "project.config" \
+          --add access."refs/meta/config".read "group Visible-All-Projects-Config"
+      git config -f "project.config" \
+          --add capability.viewTaskPaths "group Administrators"
+      q git add . && q git commit -m "project config update"
+      q git push origin HEAD:refs/meta/config
+    )
+}
+
+SSH_PORT=29418
+USER_RUN_TESTS_DIR="$USER_HOME"/"$RUN_TESTS_DIR"
+while (( "$#" )) ; do
+   case "$1" in
+       --non-secret-user)               shift ; NON_SECRET_USER="$1" ;;
+       --untrusted-user)                shift ; UNTRUSTED_USER="$1" ;;
+       *)                               die "invalid argument '$1'" ;;
+   esac
+   shift
+done
+
+[ -z "$NON_SECRET_USER" ] && die "non-secret-user not set"
+[ -z "$UNTRUSTED_USER" ] && die "untrusted-user not set"
+
+"$USER_RUN_TESTS_DIR"/create-test-project-and-changes.sh
+"$USER_RUN_TESTS_DIR"/update-all-users-project.sh
+create_test_users_and_group
+setup_all_projects_repo
\ No newline at end of file
diff --git a/test/docker/run_tests/start.sh b/test/docker/run_tests/start.sh
index 5104677..1d31d0b 100755
--- a/test/docker/run_tests/start.sh
+++ b/test/docker/run_tests/start.sh
@@ -24,13 +24,13 @@
 
 is_plugin_loaded "task" || die "Task plugin is not installed"
 
-./"$USER_RUN_TESTS_DIR"/create-test-project-and-changes.sh
-./"$USER_RUN_TESTS_DIR"/update-all-users-project.sh
+NON_SECRET_USER="non_secret_user"
+UNTRUSTED_USER="untrusted_user"
+"$USER_RUN_TESTS_DIR"/create-one-time-test-data.sh --non-secret-user "$NON_SECRET_USER" \
+    --untrusted-user "$UNTRUSTED_USER"
 
 echo "Running Task plugin tests ..."
-untrusted_user="untrusted_user"
-ssh -p 29418 "$GERRIT_HOST" gerrit create-account "$untrusted_user" --full-name "$untrusted_user" \
-      --email "$untrusted_user"@example.com --ssh-key - < ~/.ssh/id_rsa.pub
 
 cd "$USER_RUN_TESTS_DIR"/../../ && ./check_task_statuses.sh \
-    --server "$GERRIT_HOST" --untrusted-user "$untrusted_user"
+    --server "$GERRIT_HOST" --non-secret-user "$NON_SECRET_USER" \
+    --untrusted-user "$UNTRUSTED_USER"
diff --git a/test/docker/run_tests/update-all-users-project.sh b/test/docker/run_tests/update-all-users-project.sh
index 55e879a..ee78a68 100755
--- a/test/docker/run_tests/update-all-users-project.sh
+++ b/test/docker/run_tests/update-all-users-project.sh
@@ -15,10 +15,4 @@
    access."refs/*".read "deny group Anonymous Users"
 echo -e "global:Registered-Users\tRegistered Users" >> groups
 echo -e "global:Anonymous-Users\tAnonymous Users" >> groups
-git add . && git commit -m "project config update" && git push origin HEAD:refs/meta/config
-
-echo "Modifying All-Projects project ..."
-cd "$WORKSPACE" && git clone ssh://"$GERRIT_HOST":29418/All-Projects allProjects && cd allProjects
-git fetch origin refs/meta/config && git checkout FETCH_HEAD
-git config -f "project.config" --add access."refs/meta/config".read "group Registered Users"
 git add . && git commit -m "project config update" && git push origin HEAD:refs/meta/config
\ No newline at end of file