Commit 09b3a133 authored by Kostis Trantzas's avatar Kostis Trantzas
Browse files

Adding unit tests

parent ae25bf41
Loading
Loading
Loading
Loading
Loading

.classpath

deleted100644 → 0
+0 −40
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" output="target/classes" path="src/main/java">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
			<attribute name="optional" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
			<attribute name="test" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
			<attribute name="test" value="true"/>
			<attribute name="optional" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="output" path="target/classes"/>
</classpath>
+0 −6
Original line number Diff line number Diff line
eclipse.preferences.version=1
encoding//src/main/java=utf-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=utf-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8
+18 −0
Original line number Diff line number Diff line
@@ -38,6 +38,19 @@
	</distributionManagement>


	<dependencyManagement>
		<dependencies>
			<!-- Spring Boot BOM -->
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>${spring-boot-version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.projectlombok</groupId>
@@ -50,5 +63,10 @@
			<artifactId>org.etsi.osl.model.tmf</artifactId>
			<version>${org.etsi.osl.model.tmf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>
 No newline at end of file
+170 −0
Original line number Diff line number Diff line
package org.etsi.osl.domain.model.kubernetes;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import org.etsi.osl.tmf.ri639.model.ResourceAdministrativeStateType;
import org.etsi.osl.tmf.ri639.model.ResourceCreate;
import org.etsi.osl.tmf.ri639.model.ResourceHealth;
import org.etsi.osl.tmf.ri639.model.ResourceOperationalStateType;
import org.etsi.osl.tmf.ri639.model.ResourceStatusType;
import org.etsi.osl.tmf.ri639.model.ResourceUpdate;
import org.etsi.osl.tmf.ri639.model.ResourceUsageStateType;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

/**
 * The ITU-T X.731 state that {@link KubernetesCRV1#toResourceCreate()} declares on the resource,
 * from what the producer (the cridge watcher) reported.
 *
 * <p>Two contracts have to hold at once:
 *
 * <ul>
 * <li>the operationalState/administrativeState pair is spelled out exactly as
 * {@code Resource.applyHealth} spells it, so that {@code Resource.deriveHealth()} on the inventory
 * side reads back the verdict the producer gave — that pair is what
 * {@code Service.findNextStateBasedOnResourceList} folds into the service state;
 * <li>{@code resourceStatus} (pool bookkeeping) and the state attributes are independent: neither
 * one is derived from the other.
 * </ul>
 */
public class KubernetesCRV1ApplyStateTest {

  private static KubernetesCRV1.KubernetesCRV1Builder aCR() {
    // the spec UUID is the only thing toResourceCreate() refuses to work without
    return KubernetesCRV1.builder().osl_KUBCRV1_RSPEC_UUID("rspec-uuid").name("a-cr");
  }

  private static void assertState(ResourceUpdate rs,
      ResourceOperationalStateType oper, ResourceAdministrativeStateType admin) {
    assertEquals(oper, rs.getOperationalState(), "operationalState");
    assertEquals(admin, rs.getAdministrativeState(), "administrativeState");
  }

  /**
   * A CR whose producer said nothing about its state. Both attributes stay unset: on the inventory
   * side that derives as {@code PENDING}, which neither promotes nor demotes the supported service.
   * In particular there is no {@code operationalState=ENABLE} default any more — that used to be
   * declared unconditionally, and with {@code administrativeState} unset it was PENDING anyway.
   */
  @Test
  public void nothingReportedLeavesBothAttributesUnset() {
    ResourceCreate rs = aCR().build().toResourceCreate();

    assertState(rs, null, null);
    assertNull(rs.getUsageState());
  }

  /** The {@code healthValue} → attribute-pair translation, verdict by verdict. */
  @ParameterizedTest(name = "health={0} -> oper={1}, admin={2}")
  @CsvSource({
      "UP,      ENABLE,  UNLOCKED",
      "DOWN,    DISABLE, UNLOCKED",
      "HELD,    ENABLE,  LOCKED",
      "GONE,    DISABLE, SHUTDOWN",
      "PENDING, ,        ",
  })
  public void healthValueIsSpelledOutAsTheX731Pair(ResourceHealth health,
      ResourceOperationalStateType expectedOper, ResourceAdministrativeStateType expectedAdmin) {
    ResourceCreate rs = aCR().healthValue(health).build().toResourceCreate();

    assertState(rs, expectedOper, expectedAdmin);
  }

  /**
   * When no verdict is given the producer may still report the attributes one by one; each is
   * applied on its own and the others are left untouched.
   */
  @Test
  public void individualAttributesApplyWhenNoVerdictWasGiven() {
    ResourceCreate operOnly = aCR()
        .operationalStateValue(ResourceOperationalStateType.ENABLE)
        .build().toResourceCreate();
    assertState(operOnly, ResourceOperationalStateType.ENABLE, null);

    ResourceCreate all = aCR()
        .operationalStateValue(ResourceOperationalStateType.DISABLE)
        .administrativeStateValue(ResourceAdministrativeStateType.LOCKED)
        .usageStateValue(ResourceUsageStateType.BUSY)
        .build().toResourceCreate();
    assertState(all, ResourceOperationalStateType.DISABLE, ResourceAdministrativeStateType.LOCKED);
    assertEquals(ResourceUsageStateType.BUSY, all.getUsageState());
  }

  /**
   * A verdict is authoritative: individual operational/administrative values reported alongside
   * it do not override the pair it implies. (This pins the precedence the implementation and its
   * Javadoc agree on; the field-level comment on {@code healthValue} currently claims the
   * opposite.)
   */
  @Test
  public void healthValueWinsOverIndividualOperAndAdminValues() {
    ResourceCreate rs = aCR()
        .healthValue(ResourceHealth.UP)
        .operationalStateValue(ResourceOperationalStateType.DISABLE)
        .administrativeStateValue(ResourceAdministrativeStateType.LOCKED)
        .build().toResourceCreate();

    assertState(rs, ResourceOperationalStateType.ENABLE, ResourceAdministrativeStateType.UNLOCKED);
  }

  // /**
  //  * Usage state is orthogonal to health — {@link ResourceHealth} deliberately does not consult it —
  //  * so a reported {@code usageStateValue} must survive a {@code healthValue} being present.
  //  */
  // @Test
  // public void usageStateIsAppliedEvenWhenAVerdictWasGiven() {
  //   ResourceCreate rs = aCR()
  //       .healthValue(ResourceHealth.UP)
  //       .usageStateValue(ResourceUsageStateType.BUSY)
  //       .build().toResourceCreate();

  //   assertState(rs, ResourceOperationalStateType.ENABLE, ResourceAdministrativeStateType.UNLOCKED);
  //   assertEquals(ResourceUsageStateType.BUSY, rs.getUsageState());
  // }

  /**
   * The watcher stamps {@link KubernetesCRV1#OSL_LABEL_DELETED} on a CR it saw disappear from the
   * cluster. That is GONE whatever else was reported, including a stale UP verdict.
   */
  @Test
  public void deletedLabelIsGoneWhateverElseWasReported() {
    KubernetesCRV1 cr = aCR()
        .healthValue(ResourceHealth.UP)
        .operationalStateValue(ResourceOperationalStateType.ENABLE)
        .administrativeStateValue(ResourceAdministrativeStateType.UNLOCKED)
        .build();
    cr.getProperties().put(KubernetesCRV1.OSL_LABEL_DELETED, "DELETED");

    ResourceCreate rs = cr.toResourceCreate();

    assertState(rs, ResourceOperationalStateType.DISABLE, ResourceAdministrativeStateType.SHUTDOWN);
  }

  /**
   * {@code statusValue} is pool bookkeeping. It is passed through to {@code resourceStatus} and
   * must play no part in the health attributes — an {@code ALARM} does not make the CR DOWN, and an
   * {@code AVAILABLE} does not make it UP.
   */
  @ParameterizedTest(name = "resourceStatus={0} does not touch health")
  @CsvSource({"ALARM", "AVAILABLE", "RESERVED", "UNKNOWN"})
  public void resourceStatusIsPassedThroughAndNeverDrivesHealth(ResourceStatusType status) {
    ResourceCreate silent = aCR().statusValue(status).build().toResourceCreate();
    assertEquals(status, silent.getResourceStatus());
    assertState(silent, null, null);

    ResourceCreate up = aCR().statusValue(status).healthValue(ResourceHealth.UP)
        .build().toResourceCreate();
    assertEquals(status, up.getResourceStatus());
    assertState(up, ResourceOperationalStateType.ENABLE, ResourceAdministrativeStateType.UNLOCKED);
  }

  /** The update path is the create path; the watcher uses both depending on what it already knows. */
  @Test
  public void toResourceUpdateDeclaresTheSameState() {
    ResourceUpdate rs = aCR().healthValue(ResourceHealth.DOWN).build().toResourceUpdate();

    assertState(rs, ResourceOperationalStateType.DISABLE, ResourceAdministrativeStateType.UNLOCKED);
  }
}