modeldb-main/backend/server/src/test/java/ai/verta/modeldb/versioning/blob/visitors/ValidatorBlobTest.java
package ai.verta.modeldb.versioning.blob.visitors;

import static org.junit.Assert.fail;

import ai.verta.modeldb.common.exceptions.ModelDBException;
import ai.verta.modeldb.versioning.Blob;
import ai.verta.modeldb.versioning.CodeBlob;
import ai.verta.modeldb.versioning.ConfigBlob;
import ai.verta.modeldb.versioning.ContinuousHyperparameterSetConfigBlob;
import ai.verta.modeldb.versioning.DatasetBlob;
import ai.verta.modeldb.versioning.DockerEnvironmentBlob;
import ai.verta.modeldb.versioning.EnvironmentBlob;
import ai.verta.modeldb.versioning.EnvironmentVariablesBlob;
import ai.verta.modeldb.versioning.EnvironmentVariablesBlob.Builder;
import ai.verta.modeldb.versioning.GitCodeBlob;
import ai.verta.modeldb.versioning.HyperparameterSetConfigBlob;
import ai.verta.modeldb.versioning.HyperparameterValuesConfigBlob;
import ai.verta.modeldb.versioning.PathDatasetBlob;
import ai.verta.modeldb.versioning.PathDatasetComponentBlob;
import ai.verta.modeldb.versioning.PythonEnvironmentBlob;
import ai.verta.modeldb.versioning.PythonRequirementEnvironmentBlob;
import ai.verta.modeldb.versioning.VersionEnvironmentBlob;
import ai.verta.modeldb.versioning.autogenerated._public.modeldb.versioning.model.AutogenBlob;
import io.grpc.Status.Code;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/*
Examples:
environment {
  docker {
    sha: "test_sha"
  }
}

config {
  hyperparameter_set {
    name: "test"
    continuous {
      interval_begin {
        string_value: "test"
      }
    }
  }
}

environment {
  environment_variables {
    name: "Env"
    value: "ASDF"
  }
  environment_variables {
    name: "Env"
    value: "ASDF2"
  }
}

code {
  git {
    is_dirty: true
  }
}

config {
  hyperparameter_set {
    continuous {
      interval_begin {
        string_value: "1"
      }
    }
  }
}

dataset {
  path {
    components {
      size: 3
    }
  }
}

environment {
  python {
    requirements {
      library: "numpy"
      version {
        major: 3
      }
    }
    requirements {
      library: "numpy"
      version {
        major: 3
      }
    }
  }
}
environment {
  python {
    constraints {
      library: "numpy"
      version {
        major: 3
      }
    }
    constraints {
      library: "numpy"
      version {
        major: 3
      }
    }
  }
}

environment {
  python {
    constraints {
      version {
        patch: 6
      }
    }
  }
}
 */
@RunWith(Parameterized.class)
public class ValidatorBlobTest {
  private static final Logger LOGGER = LogManager.getLogger(ValidatorBlobTest.class);
  private static final Validator validator = new Validator();
  private static final Builder BUILDER_FOR_VAR =
      EnvironmentVariablesBlob.newBuilder().setName("Env").setValue("ASDF");
  private static final Builder BUILDER_FOR_VAR2 =
      EnvironmentVariablesBlob.newBuilder().setName("Env").setValue("ASDF2");
  private static final PythonRequirementEnvironmentBlob.Builder NUMPY =
      PythonRequirementEnvironmentBlob.newBuilder()
          .setLibrary("numpy")
          .setVersion(VersionEnvironmentBlob.newBuilder().setMajor(3).build());
  private static final Blob.Builder[] blobs = {
    Blob.newBuilder(),
    Blob.newBuilder()
        .setEnvironment(
            EnvironmentBlob.newBuilder()
                .setDocker(DockerEnvironmentBlob.newBuilder().setSha("test_sha"))),
    Blob.newBuilder()
        .setConfig(
            ConfigBlob.newBuilder()
                .addHyperparameterSet(
                    HyperparameterSetConfigBlob.newBuilder()
                        .setName("test")
                        .setContinuous(
                            ContinuousHyperparameterSetConfigBlob.newBuilder()
                                .setIntervalBegin(
                                    HyperparameterValuesConfigBlob.newBuilder()
                                        .setStringValue("test"))))),
    Blob.newBuilder()
        .setEnvironment(
            EnvironmentBlob.newBuilder()
                .addEnvironmentVariables(BUILDER_FOR_VAR)
                .addEnvironmentVariables(BUILDER_FOR_VAR2)),
    Blob.newBuilder()
        .setCode(CodeBlob.newBuilder().setGit(GitCodeBlob.newBuilder().setIsDirty(true))),
    Blob.newBuilder()
        .setConfig(
            ConfigBlob.newBuilder()
                .addHyperparameterSet(
                    HyperparameterSetConfigBlob.newBuilder()
                        .setContinuous(
                            ContinuousHyperparameterSetConfigBlob.newBuilder()
                                .setIntervalBegin(
                                    HyperparameterValuesConfigBlob.newBuilder()
                                        .setStringValue("1"))))),
    Blob.newBuilder()
        .setDataset(
            DatasetBlob.newBuilder()
                .setPath(
                    PathDatasetBlob.newBuilder()
                        .addComponents(PathDatasetComponentBlob.newBuilder().setSize(3)))),
    Blob.newBuilder()
        .setEnvironment(
            EnvironmentBlob.newBuilder()
                .setPython(
                    PythonEnvironmentBlob.newBuilder()
                        .addRequirements(NUMPY)
                        .addRequirements(NUMPY))),
    Blob.newBuilder()
        .setEnvironment(
            EnvironmentBlob.newBuilder()
                .setPython(
                    PythonEnvironmentBlob.newBuilder()
                        .addConstraints(NUMPY)
                        .addConstraints(NUMPY))),
    Blob.newBuilder()
        .setEnvironment(
            EnvironmentBlob.newBuilder()
                .setPython(
                    PythonEnvironmentBlob.newBuilder()
                        .addConstraints(
                            PythonRequirementEnvironmentBlob.newBuilder()
                                .setVersion(VersionEnvironmentBlob.newBuilder().setPatch(6)))))
  };
  private final Blob blob;

  @Parameters
  public static Collection<Object[]> data() {
    List<Object[]> result = new LinkedList<>();
    for (Blob.Builder b : blobs) {
      result.add(new Object[] {b.build()});
    }
    return result;
  }

  public ValidatorBlobTest(Blob blob) {
    this.blob = blob;
  }

  @Test
  public void testValidateBlob() {
    try {
      validator.validate(AutogenBlob.fromProto(blob));
      fail("Expected exception has not occurred");
    } catch (ModelDBException e) {
      LOGGER.info(e.getMessage());
      Assert.assertEquals(Code.INVALID_ARGUMENT, e.getCode());
    }
  }
}
