// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.acceptance.rest.account;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.junit.Test;

import java.io.IOException;

public class CapabilitiesIT extends AbstractDaemonTest {

  @Test
  public void testCapabilitiesUser() throws Exception {
    grantAllCapabilities();
    RestResponse r =
        userSession.get("/accounts/self/capabilities");
    int code = r.getStatusCode();
    assertEquals(code, 200);
    CapabilityInfo info = (new Gson()).fromJson(r.getReader(),
        new TypeToken<CapabilityInfo>() {}.getType());
    for (String c: GlobalCapability.getAllNames()) {
      if (GlobalCapability.ADMINISTRATE_SERVER.equals(c)) {
        assertFalse(info.administrateServer);
      } else if (GlobalCapability.PRIORITY.equals(c)) {
        assertFalse(info.priority);
      } else if (GlobalCapability.QUERY_LIMIT.equals(c)) {
        assertEquals(0, info.queryLimit.min);
        assertEquals(0, info.queryLimit.max);
      } else {
        assertTrue(String.format("capability %s was not granted", c),
            (Boolean)CapabilityInfo.class.getField(c).get(info));
      }
    }
  }

  @Test
  public void testCapabilitiesAdmin() throws Exception {
    RestResponse r =
        adminSession.get("/accounts/self/capabilities");
    int code = r.getStatusCode();
    assertEquals(code, 200);
    CapabilityInfo info = (new Gson()).fromJson(r.getReader(),
        new TypeToken<CapabilityInfo>() {}.getType());
    for (String c: GlobalCapability.getAllNames()) {
      if (GlobalCapability.PRIORITY.equals(c)) {
        assertFalse(info.priority);
      } else if (GlobalCapability.QUERY_LIMIT.equals(c)) {
        assertNotNull("missing queryLimit", info.queryLimit);
        assertEquals(0, info.queryLimit.min);
        assertEquals(500, info.queryLimit.max);
      } else if (GlobalCapability.ACCESS_DATABASE.equals(c)) {
        assertFalse(info.accessDatabase);
      } else if (GlobalCapability.RUN_AS.equals(c)) {
        assertFalse(info.runAs);
      } else {
        assertTrue(String.format("capability %s was not granted", c),
            (Boolean)CapabilityInfo.class.getField(c).get(info));
      }
    }
  }

  private void grantAllCapabilities() throws IOException,
      ConfigInvalidException {
    MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
    md.setMessage("Make super user");
    ProjectConfig config = ProjectConfig.read(md);
    AccessSection s = config.getAccessSection(
        AccessSection.GLOBAL_CAPABILITIES);
    for (String c: GlobalCapability.getAllNames()) {
      if (GlobalCapability.ADMINISTRATE_SERVER.equals(c)) {
        continue;
      }
      Permission p = s.getPermission(c, true);
      p.add(new PermissionRule(
          config.resolve(SystemGroupBackend.getGroup(
              SystemGroupBackend.REGISTERED_USERS))));
    }
    config.commit(md);
    projectCache.evict(config.getProject());
  }
}

@@ -650,24 +650,484 @@
 t.account;%0A%0A
+import static com.google.gerrit.common.data.GlobalCapability.ACCESS_DATABASE;%0Aimport static com.google.gerrit.common.data.GlobalCapability.ADMINISTRATE_SERVER;%0Aimport static com.google.gerrit.common.data.GlobalCapability.DEFAULT_MAX_QUERY_LIMIT;%0Aimport static com.google.gerrit.common.data.GlobalCapability.PRIORITY;%0Aimport static com.google.gerrit.common.data.GlobalCapability.QUERY_LIMIT;%0Aimport static com.google.gerrit.common.data.GlobalCapability.RUN_AS;%0A
 import stati
@@ -2366,32 +2366,33 @@
    for (String c
+ 
 : GlobalCapabili
@@ -2421,33 +2421,16 @@
     if (
-GlobalCapability.
 ADMINIST
@@ -2517,33 +2517,16 @@
 lse if (
-GlobalCapability.
 PRIORITY
@@ -2592,33 +2592,16 @@
 lse if (
-GlobalCapability.
 QUERY_LI
@@ -2807,32 +2807,33 @@
        (Boolean)
+ 
 CapabilityInfo.c
@@ -3213,32 +3213,33 @@
    for (String c
+ 
 : GlobalCapabili
@@ -3268,33 +3268,16 @@
     if (
-GlobalCapability.
 PRIORITY
@@ -3343,33 +3343,16 @@
 lse if (
-GlobalCapability.
 QUERY_LI
@@ -3501,11 +3501,31 @@
 als(
-500
+DEFAULT_MAX_QUERY_LIMIT
 , in
@@ -3561,33 +3561,16 @@
 lse if (
-GlobalCapability.
 ACCESS_D
@@ -3649,33 +3649,16 @@
 lse if (
-GlobalCapability.
 RUN_AS.e
@@ -3808,16 +3808,17 @@
 Boolean)
+ 
 Capabili
@@ -4226,16 +4226,17 @@
 String c
+ 
 : Global
@@ -4273,33 +4273,16 @@
     if (
-GlobalCapability.
 ADMINIST

Tidy up code style in CapabilitiesIT