/*
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */
package org.mule.runtime.module.deployment.impl.internal.artifact;

import static java.lang.Thread.currentThread;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mule.runtime.core.api.config.bootstrap.ArtifactType.DOMAIN;
import static org.mule.runtime.core.internal.config.RuntimeComponentBuildingDefinitionsUtil.getRuntimeComponentBuildingDefinitionProvider;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.CLASS_LOADER_REPOSITORY_CANNOT_BE_NULL;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.CLASS_LOADER_REPOSITORY_WAS_NOT_SET;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.EXECUTION_CLASSLOADER_WAS_NOT_SET;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.INSTALLATION_DIRECTORY_MUST_BE_A_DIRECTORY;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.MULE_CONTEXT_ARTIFACT_PROPERTIES_CANNOT_BE_NULL;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.ONLY_APPLICATIONS_OR_POLICIES_ARE_ALLOWED_TO_HAVE_A_PARENT_ARTIFACT;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.SERVICE_CONFIGURATOR_CANNOT_BE_NULL;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.SERVICE_REPOSITORY_CANNOT_BE_NULL;
import static org.mule.runtime.module.deployment.impl.internal.artifact.ArtifactContextBuilder.newBuilder;

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;

import org.mule.runtime.core.api.MuleContext;
import org.mule.runtime.deployment.model.api.DeployableArtifact;
import org.mule.runtime.module.artifact.api.classloader.ClassLoaderRepository;
import org.mule.tck.config.TestServicesConfigurationBuilder;
import org.mule.tck.junit4.AbstractMuleTestCase;

public class ArtifactContextBuilderTestCase extends AbstractMuleTestCase {

  @ClassRule
  public static TemporaryFolder temporaryFolder = new TemporaryFolder();

  @Rule
  public ExpectedException expectedException = ExpectedException.none();

  @Test
  public void emptyBuilder() throws Exception {
    MuleContext muleContext =
        newBuilder(new TestServicesConfigurationBuilder()).setExecutionClassloader(currentThread().getContextClassLoader())
            .setRuntimeComponentBuildingDefinitionProvider(getRuntimeComponentBuildingDefinitionProvider())
            .setClassLoaderRepository(mock(ClassLoaderRepository.class)).build().getMuleContext();
    assertThat(muleContext, notNullValue());
    assertThat(muleContext.isInitialised(), is(true));
    muleContext.start();
    assertThat(muleContext.isStarted(), is(true));
  }

  @Test
  public void buildWithoutClassloader() throws Exception {
    expectedException.expectMessage(EXECUTION_CLASSLOADER_WAS_NOT_SET);
    newBuilder().build();
  }

  @Test
  public void setNullArtifactProperties() throws Exception {
    expectedException.expectMessage(MULE_CONTEXT_ARTIFACT_PROPERTIES_CANNOT_BE_NULL);
    newBuilder().setArtifactProperties(null);
  }

  @Test
  public void setNullClassLoaderRepository() throws Exception {
    expectedException.expectMessage(CLASS_LOADER_REPOSITORY_CANNOT_BE_NULL);
    newBuilder().setClassLoaderRepository(null);
  }

  @Test
  public void setNullServiceConfigurator() throws Exception {
    expectedException.expectMessage(SERVICE_CONFIGURATOR_CANNOT_BE_NULL);
    newBuilder().withServiceConfigurator(null);
  }

  @Test
  public void buildWithoutClassloaderRepository() throws Exception {
    expectedException.expectMessage(CLASS_LOADER_REPOSITORY_WAS_NOT_SET);
    newBuilder().setExecutionClassloader(currentThread().getContextClassLoader()).build();
  }

  @Test
  public void setRegularFileInstallationLocation() throws Exception {
    expectedException.expectMessage(INSTALLATION_DIRECTORY_MUST_BE_A_DIRECTORY);
    newBuilder().setArtifactInstallationDirectory(temporaryFolder.newFile());
  }

  @Test
  public void buildUsingDomainAndParentArtifact() throws Exception {
    expectedException.expectMessage(ONLY_APPLICATIONS_OR_POLICIES_ARE_ALLOWED_TO_HAVE_A_PARENT_ARTIFACT);
    newBuilder().setArtifactType(DOMAIN)
        .setExecutionClassloader(currentThread().getContextClassLoader()).setParentArtifact(mock(DeployableArtifact.class))
        .setClassLoaderRepository(mock(ClassLoaderRepository.class))
        .build();
  }

  @Test
  public void setNullServiceRepository() throws Exception {
    expectedException.expectMessage(SERVICE_REPOSITORY_CANNOT_BE_NULL);
    newBuilder().setServiceRepository(null);
  }
}
