@Test
  public void crestQueryIsAllowed() throws SSOException, DelegationException, ResourceException {
    // Given...
    final Set<String> actions = new HashSet<>(Arrays.asList("READ"));
    final DelegationPermission permission =
        new DelegationPermission(
            "/abc", "rest", "1.0", "policies", "read", actions, EXTENSIONS, DUMB_FUNC);
    given(factory.newInstance("/abc", "rest", "1.0", "policies", "read", actions, EXTENSIONS))
        .willReturn(permission);

    given(subjectContext.getCallerSSOToken()).willReturn(token);
    given(evaluator.isAllowed(eq(token), eq(permission), eq(ENVIRONMENT))).willReturn(true);

    QueryResourceHandler handler = mock(QueryResourceHandler.class);
    Promise<QueryResponse, ResourceException> promise =
        Promises.newResultPromise(Responses.newQueryResponse("abc-def"));
    given(
            provider.queryCollection(
                isA(Context.class), isA(QueryRequest.class), isA(QueryResourceHandler.class)))
        .willReturn(promise);

    // When...
    final FilterChain chain = AuthorizationFilters.createAuthorizationFilter(provider, module);
    final Router router = new Router();
    router.addRoute(RoutingMode.STARTS_WITH, Router.uriTemplate("/policies"), chain);

    final RealmContext context = new RealmContext(subjectContext);
    context.setSubRealm("abc", "abc");
    final QueryRequest request = Requests.newQueryRequest("/policies");
    Promise<QueryResponse, ResourceException> result =
        router.handleQuery(context, request, handler);

    // Then...
    QueryResponse response = result.getOrThrowUninterruptibly();
    assertThat(response.getPagedResultsCookie()).isEqualTo("abc-def");
  }
  /**
   * TODO Implement this method
   *
   * <p>{@inheritDoc}
   */
  public Promise<QueryResponse, ResourceException> handleQuery(
      final Context context, final QueryRequest request, final QueryResourceHandler handler) {
    EventEntry measure =
        Publisher.start(
            Name.get(
                "openidm/internal/script/" + this.getScriptEntry().getName().getName() + "/query"),
            null,
            null);
    try {
      final ScriptEntry _scriptEntry = getScriptEntry();
      if (!_scriptEntry.isActive()) {
        throw new ServiceUnavailableException("Inactive script: " + _scriptEntry.getName());
      }
      final Script script = _scriptEntry.getScript(context);
      script.setBindings(script.createBindings());
      customizer.handleQuery(context, request, script.getBindings());

      final Function<Void> queryCallback =
          new Function<Void>() {
            @Override
            public Void call(Parameter scope, Function<?> callback, Object... arguments)
                throws ResourceException, NoSuchMethodException {
              if (arguments.length == 3 && null != arguments[2]) {
                if (arguments[2] instanceof Map) {}

                if (arguments[2] instanceof JsonValue) {

                } else {
                  throw new NoSuchMethodException(
                      FunctionFactory.getNoSuchMethodMessage("callback", arguments));
                }
              } else if (arguments.length >= 2 && null != arguments[1]) {
                if (arguments[1] instanceof Map) {}

                if (arguments[1] instanceof JsonValue) {

                } else {
                  throw new NoSuchMethodException(
                      FunctionFactory.getNoSuchMethodMessage("callback", arguments));
                }
              } else if (arguments.length >= 1 && null != arguments[0]) {
                if (arguments[0] instanceof Map) {}

                if (arguments[0] instanceof JsonValue) {

                } else {
                  throw new NoSuchMethodException(
                      FunctionFactory.getNoSuchMethodMessage("callback", arguments));
                }
              } else {
                throw new NoSuchMethodException(
                    FunctionFactory.getNoSuchMethodMessage("callback", arguments));
              }
              return null;
            }
          };
      script.putSafe("callback", queryCallback);
      Object rawResult = script.eval();
      JsonValue result = null;
      if (rawResult instanceof JsonValue) {
        result = (JsonValue) rawResult;
      } else {
        result = new JsonValue(rawResult);
      }
      QueryResponse queryResponse = newQueryResponse();
      // Script can either
      // - return null and instead use callback hook to call
      //   handleResource, handleResult, handleError
      //   careful! script MUST call handleResult or handleError itself
      // or
      // - return a result list of resources
      // or
      // - return a full query result structure
      if (!result.isNull()) {
        if (result.isList()) {
          // Script may return just the result elements as a list
          handleQueryResultList(result, handler);
        } else {
          // Or script may return a full query response structure,
          // with meta-data and results field
          if (result.isDefined(QueryResponse.FIELD_RESULT)) {
            handleQueryResultList(result.get(QueryResponse.FIELD_RESULT), handler);
            queryResponse =
                newQueryResponse(
                    result.get(QueryResponse.FIELD_PAGED_RESULTS_COOKIE).asString(),
                    result
                        .get(QueryResponse.FIELD_TOTAL_PAGED_RESULTS_POLICY)
                        .asEnum(CountPolicy.class),
                    result.get(QueryResponse.FIELD_TOTAL_PAGED_RESULTS).asInteger());
          } else {
            logger.debug("Script returned unexpected query result structure: ", result.getObject());
            return new InternalServerErrorException(
                    "Script returned unexpected query result structure of type "
                        + result.getObject().getClass())
                .asPromise();
          }
        }
      }
      return queryResponse.asPromise();
    } catch (ScriptException e) {
      return convertScriptException(e).asPromise();
    } catch (ResourceException e) {
      return e.asPromise();
    } catch (Exception e) {
      return new InternalServerErrorException(e.getMessage(), e).asPromise();
    } finally {
      measure.end();
    }
  }