package com.yahoo.labs.samoa.core;

/*
 * #%L
 * SAMOA
 * %%
 * Copyright (C) 2014 - 2015 Apache Software Foundation
 * %%
 * 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.
 * #L%
 */

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class DoubleVectorTest {
  private DoubleVector emptyVector, array5Vector;

  @Before
  public void setUp() {
    emptyVector = new DoubleVector();
    array5Vector = new DoubleVector(new double[] { 1.1, 2.5, 0, 4.7, 0 });
  }

  @Test
  public void testGetArrayRef() {
    assertThat(emptyVector.getArrayRef(), notNullValue());
    assertTrue(emptyVector.getArrayRef() == emptyVector.getArrayRef());
    assertEquals(5, array5Vector.getArrayRef().length);
  }

  @Test
  public void testGetArrayCopy() {
    double[] arrayRef;
    arrayRef = emptyVector.getArrayRef();
    assertTrue(arrayRef != emptyVector.getArrayCopy());
    assertThat(arrayRef, is(equalTo(emptyVector.getArrayCopy())));

    arrayRef = array5Vector.getArrayRef();
    assertTrue(arrayRef != array5Vector.getArrayCopy());
    assertThat(arrayRef, is(equalTo(array5Vector.getArrayCopy())));
  }

  @Test
  public void testNumNonZeroEntries() {
    assertEquals(0, emptyVector.numNonZeroEntries());
    assertEquals(3, array5Vector.numNonZeroEntries());
  }

  @Test(expected = IndexOutOfBoundsException.class)
  public void testGetValueOutOfBound() {
    @SuppressWarnings("unused")
    double value = emptyVector.getArrayRef()[0];
  }

  @Test()
  public void testSetValue() {
    // test automatic vector enlargement
    emptyVector.setValue(0, 1.0);
    assertEquals(1, emptyVector.getArrayRef().length);
    assertEquals(1.0, emptyVector.getArrayRef()[0], 0.0); // should be exactly the same, so delta=0.0

    emptyVector.setValue(5, 5.5);
    assertEquals(6, emptyVector.getArrayRef().length);
    assertEquals(2, emptyVector.numNonZeroEntries());
    assertEquals(5.5, emptyVector.getArrayRef()[5], 0.0); // should be exactly the same, so delta=0.0
  }

  @Test
  public void testAddToValue() {
    array5Vector.addToValue(2, 5.0);
    assertEquals(5, array5Vector.getArrayRef()[2], 0.0); // should be exactly the same, so delta=0.0

    // test automatic vector enlargement
    emptyVector.addToValue(0, 1.0);
    assertEquals(1, emptyVector.getArrayRef()[0], 0.0); // should be exactly the same, so delta=0.0
  }

  @Test
  public void testSumOfValues() {
    assertEquals(1.1 + 2.5 + 4.7, array5Vector.sumOfValues(), Double.MIN_NORMAL);
  }

}
