// Copyright (C) 2016 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.server.account;

import static com.google.common.truth.Truth.assertThat;

import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.junit.Test;

public class AuthorizedKeysTest {
  private static final String KEY1 =
      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCgug5VyMXQGnem2H1KVC4/HcRcD4zzBqS"
          + "uJBRWVonSSoz3RoAZ7bWXCVVGwchtXwUURD689wFYdiPecOrWOUgeeyRq754YWRhU+W28"
          + "vf8IZixgjCmiBhaL2gt3wff6pP+NXJpTSA4aeWE5DfNK5tZlxlSxqkKOS8JRSUeNQov5T"
          + "w== john.doe@example.com";
  private static final String KEY2 =
      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDm5yP7FmEoqzQRDyskX+9+N0q9GrvZeh5"
          + "RG52EUpE4ms/Ujm3ewV1LoGzc/lYKJAIbdcZQNJ9+06EfWZaIRA3oOwAPe1eCnX+aLr8E"
          + "6Tw2gDMQOGc5e9HfyXpC2pDvzauoZNYqLALOG3y/1xjo7IH8GYRS2B7zO/Mf9DdCcCKSf"
          + "w== john.doe@example.com";
  private static final String KEY3 =
      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCaS7RHEcZ/zjl9hkWkqnm29RNr2OQ/TZ5"
          + "jk2qBVMH3BgzPsTsEs+7ag9tfD8OCj+vOcwm626mQBZoR2e3niHa/9gnHBHFtOrGfzKbp"
          + "RjTWtiOZbB9HF+rqMVD+Dawo/oicX/dDg7VAgOFSPothe6RMhbgWf84UcK5aQd5eP5y+t"
          + "Q== john.doe@example.com";
  private static final String KEY4 =
      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDIJzW9BaAeO+upFletwwEBnGS15lJmS5i"
          + "08/NiFef0jXtNNKcLtnd13bq8jOi5VA2is0bwof1c8YbwcvUkdFa8RL5aXoyZBpfYZsWs"
          + "/YBLZGiHy5rjooMZQMnH37A50cBPnXr0AQz0WRBxLDBDyOZho+O/DfYAKv4rzPSQ3yw4+"
          + "w== john.doe@example.com";
  private static final String KEY5 =
      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCgBRKGhiXvY6D9sM+Vbth5Kate57YF7kD"
          + "rqIyUiYIMJK93/AXc8qR/J/p3OIFQAxvLz1qozAur3j5HaiwvxVU19IiSA0vafdhaDLRi"
          + "zRuEL5e/QOu9yGq9xkWApCmg6edpWAHG+Bx4AldU78MiZvzoB7gMMdxc9RmZ1gYj/DjxV"
          + "w== john.doe@example.com";

  @Test
  public void test() throws Exception {
    List<Optional<AccountSshKey>> keys = new ArrayList<>();
    StringBuilder expected = new StringBuilder();
    assertSerialization(keys, expected);
    assertParse(expected, keys);

    expected.append(addKey(keys, KEY1));
    assertSerialization(keys, expected);
    assertParse(expected, keys);

    expected.append(addKey(keys, KEY2));
    assertSerialization(keys, expected);
    assertParse(expected, keys);

    expected.append(addInvalidKey(keys, KEY3));
    assertSerialization(keys, expected);
    assertParse(expected, keys);

    expected.append(addKey(keys, KEY4));
    assertSerialization(keys, expected);
    assertParse(expected, keys);

    expected.append(addDeletedKey(keys));
    assertSerialization(keys, expected);
    assertParse(expected, keys);

    expected.append(addKey(keys, KEY5));
    assertSerialization(keys, expected);
    assertParse(expected, keys);
  }

  @Test
  public void parseWindowsLineEndings() throws Exception {
    List<Optional<AccountSshKey>> keys = new ArrayList<>();
    StringBuilder authorizedKeys = new StringBuilder();
    authorizedKeys.append(toWindowsLineEndings(addKey(keys, KEY1)));
    assertParse(authorizedKeys, keys);

    authorizedKeys.append(toWindowsLineEndings(addKey(keys, KEY2)));
    assertParse(authorizedKeys, keys);

    authorizedKeys.append(toWindowsLineEndings(addInvalidKey(keys, KEY3)));
    assertParse(authorizedKeys, keys);

    authorizedKeys.append(toWindowsLineEndings(addKey(keys, KEY4)));
    assertParse(authorizedKeys, keys);

    authorizedKeys.append(toWindowsLineEndings(addDeletedKey(keys)));
    assertParse(authorizedKeys, keys);

    authorizedKeys.append(toWindowsLineEndings(addKey(keys, KEY5)));
    assertParse(authorizedKeys, keys);
  }

  private static String toWindowsLineEndings(String s) {
    return s.replaceAll("\n", "\r\n");
  }

  private static void assertSerialization(
      List<Optional<AccountSshKey>> keys, StringBuilder expected) {
    assertThat(AuthorizedKeys.serialize(keys)).isEqualTo(expected.toString());
  }

  private static void assertParse(
      StringBuilder authorizedKeys, List<Optional<AccountSshKey>> expectedKeys) {
    Account.Id accountId = new Account.Id(1);
    List<Optional<AccountSshKey>> parsedKeys =
        AuthorizedKeys.parse(accountId, authorizedKeys.toString());
    assertThat(parsedKeys).containsExactlyElementsIn(expectedKeys);
    int seq = 1;
    for (Optional<AccountSshKey> sshKey : parsedKeys) {
      if (sshKey.isPresent()) {
        assertThat(sshKey.get().getAccount()).isEqualTo(accountId);
        assertThat(sshKey.get().getKey().get()).isEqualTo(seq);
      }
      seq++;
    }
  }

  /**
   * Adds the given public key as new SSH key to the given list.
   *
   * @return the expected line for this key in the authorized_keys file
   */
  private static String addKey(List<Optional<AccountSshKey>> keys, String pub) {
    AccountSshKey.Id keyId = new AccountSshKey.Id(new Account.Id(1), keys.size() + 1);
    AccountSshKey key = new AccountSshKey(keyId, pub);
    keys.add(Optional.of(key));
    return key.getSshPublicKey() + "\n";
  }

  /**
   * Adds the given public key as invalid SSH key to the given list.
   *
   * @return the expected line for this key in the authorized_keys file
   */
  private static String addInvalidKey(List<Optional<AccountSshKey>> keys, String pub) {
    AccountSshKey.Id keyId = new AccountSshKey.Id(new Account.Id(1), keys.size() + 1);
    AccountSshKey key = new AccountSshKey(keyId, pub);
    key.setInvalid();
    keys.add(Optional.of(key));
    return AuthorizedKeys.INVALID_KEY_COMMENT_PREFIX + key.getSshPublicKey() + "\n";
  }

  /**
   * Adds a deleted SSH key to the given list.
   *
   * @return the expected line for this key in the authorized_keys file
   */
  private static String addDeletedKey(List<Optional<AccountSshKey>> keys) {
    keys.add(Optional.empty());
    return AuthorizedKeys.DELETED_KEY_COMMENT + "\n";
  }
}
