/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

#include <catch.hpp>
#include <memory>

#include "AuxHashMap.hpp"

namespace datasketches {

TEST_CASE("aux hash map: check must replace", "[aux_hash_map]") {
  AuxHashMap<std::allocator<uint8_t>>* map = new AuxHashMap<std::allocator<uint8_t>>(3, 7, std::allocator<uint8_t>());
  map->mustAdd(100, 5);
  int val = map->mustFindValueFor(100);
  REQUIRE(val == 5);

  map->mustReplace(100, 10);
  val = map->mustFindValueFor(100);
  REQUIRE(val == 10);

  REQUIRE_THROWS_AS(map->mustReplace(101, 5), std::invalid_argument);

  delete map;
}

TEST_CASE("aux hash map: check grow space", "[aux_hash_map]") {
  auto map = std::unique_ptr<AuxHashMap<std::allocator<uint8_t>>, std::function<void(AuxHashMap<std::allocator<uint8_t>>*)>>(
      AuxHashMap<std::allocator<uint8_t>>::newAuxHashMap(3, 7, std::allocator<uint8_t>()),
      AuxHashMap<std::allocator<uint8_t>>::make_deleter()
      );
  REQUIRE(map->getLgAuxArrInts() == 3);
  for (int i = 1; i <= 7; ++i) {
    map->mustAdd(i, i);
  }
  REQUIRE(map->getLgAuxArrInts() == 4);
  auto itr = map->begin(true);
  int count1 = 0;
  int count2 = 0;
  while (itr != map->end()) {
    ++count2;
    int pair = *itr;
    if (pair != 0) { ++count1; }
    ++itr;
  }
  REQUIRE(count1 == 7);
  REQUIRE(count2 == 16);
}

TEST_CASE("aux hash map: check exception must find value for", "[aux_hash_map]") {
  AuxHashMap<std::allocator<uint8_t>> map(3, 7, std::allocator<uint8_t>());
  map.mustAdd(100, 5);
  REQUIRE_THROWS_AS(map.mustFindValueFor(101), std::invalid_argument);
}

TEST_CASE("aux hash map: check exception must add", "[aux_hash_map]") {
  AuxHashMap<std::allocator<uint8_t>>* map = AuxHashMap<std::allocator<uint8_t>>::newAuxHashMap(3, 7, std::allocator<uint8_t>());
  map->mustAdd(100, 5);
  REQUIRE_THROWS_AS(map->mustAdd(100, 6), std::invalid_argument);
  
  AuxHashMap<std::allocator<uint8_t>>::make_deleter()(map);
}

} /* namespace datasketches */
