javatests/com/google/cloud/deploymentmanager/autogen/SoyFunctionsTest.java (552 lines of code) (raw):

// Copyright 2018 Google LLC // // 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. package com.google.cloud.deploymentmanager.autogen; import static com.google.cloud.deploymentmanager.autogen.proto.DeployInputSection.Placement.CUSTOM_BOTTOM; import static com.google.cloud.deploymentmanager.autogen.proto.DeployInputSection.Placement.MAIN; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.BooleanExpressionDisplayCondition; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.DependentTiers; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.DeployInputFieldName; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.FindDeployInputField; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.FindDisplayGroup; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.FindInputTestDefaultValue; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.FindInputsWithTestDefaultValues; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.FindVmTier; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.ListDeployInputFields; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.SolutionHasGpus; import com.google.cloud.deploymentmanager.autogen.SoyFunctions.TierPrefixed; import com.google.cloud.deploymentmanager.autogen.proto.AcceleratorSpec; import com.google.cloud.deploymentmanager.autogen.proto.BooleanExpression; import com.google.cloud.deploymentmanager.autogen.proto.BooleanExpression.BooleanDeployInputField; import com.google.cloud.deploymentmanager.autogen.proto.BooleanExpression.ExternalIpAvailability; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputField; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputField.BooleanCheckbox; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputField.GroupedBooleanCheckbox; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputField.GroupedBooleanCheckbox.DisplayGroup; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputField.IntegerBox; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputField.StringBox; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputSection; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputSection.Placement; import com.google.cloud.deploymentmanager.autogen.proto.DeployInputSpec; import com.google.cloud.deploymentmanager.autogen.proto.GceMetadataItem; import com.google.cloud.deploymentmanager.autogen.proto.GceMetadataItem.TierVmNames; import com.google.cloud.deploymentmanager.autogen.proto.MultiVmDeploymentPackageSpec; import com.google.cloud.deploymentmanager.autogen.proto.OptionalInt32; import com.google.cloud.deploymentmanager.autogen.proto.SingleVmDeploymentPackageSpec; import com.google.cloud.deploymentmanager.autogen.proto.VmTierSpec; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.collect.ImmutableList; import com.google.common.truth.IterableSubject; import com.google.common.truth.Subject; import com.google.common.truth.ThrowableSubject; import com.google.errorprone.annotations.CheckReturnValue; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.template.soy.data.SoyList; import com.google.template.soy.data.SoyValue; import com.google.template.soy.data.SoyValueConverter; import com.google.template.soy.data.restricted.StringData; import com.google.template.soy.shared.restricted.SoyJavaFunction; import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Tests {@link SoyFunctions}. */ @RunWith(JUnit4.class) public class SoyFunctionsTest { @Inject DependentTiers dependentTiers; @Inject DeployInputFieldName deployInputFieldName; @Inject FindInputsWithTestDefaultValues findInputsWithTestDefaultValues; @Inject FindInputTestDefaultValue findInputTestDefaultValue; @Inject FindDeployInputField findDeployInputField; @Inject FindDisplayGroup findDisplayGroup; @Inject FindVmTier findVmTier; @Inject TierPrefixed tierPrefixed; @Inject ListDeployInputFields listDeployInputFields; @Inject BooleanExpressionDisplayCondition booleanExpressionDisplayCondition; @Inject SolutionHasGpus solutionHasGpus; @Before public void setupInjector() { Guice.createInjector().injectMembers(this); } @Test public void testDependentTiers_gceMetadataItemsVmNames() { List<VmTierSpec> vmTiers = ImmutableList.of( VmTierSpec.newBuilder().setName("tier0").build(), VmTierSpec.newBuilder().setName("tier1").build(), VmTierSpec.newBuilder().setName("tier2").build()); VmTierSpec tier = VmTierSpec.newBuilder() .addGceMetadataItems( GceMetadataItem.newBuilder() .setTierVmNames(TierVmNames.newBuilder().setTier("tier0"))) .addGceMetadataItems( GceMetadataItem.newBuilder() .setTierVmNames(TierVmNames.newBuilder().setTier("tier2"))) .build(); assertFunctionCall(dependentTiers, tier, vmTiers) .hasIterableResultThat() .containsExactly(toSoyValue(vmTiers.get(0)), toSoyValue(vmTiers.get(2))); } @Test public void testDependentTiers_gceMetadataItemsVmNamesWithInvalidTier() { List<VmTierSpec> vmTiers = ImmutableList.of( VmTierSpec.newBuilder().setName("tier0").build(), VmTierSpec.newBuilder().setName("tier1").build(), VmTierSpec.newBuilder().setName("tier2").build()); VmTierSpec tier = VmTierSpec.newBuilder() .addGceMetadataItems( GceMetadataItem.newBuilder() .setTierVmNames(TierVmNames.newBuilder().setTier("tier10"))) .build(); assertFunctionCall(dependentTiers, tier, vmTiers) .throwsExceptionThat(IllegalArgumentException.class) .hasMessageThat() .startsWith("Unable to find tier"); } @Test public void testDeployInputFieldName() { assertFunctionCall( deployInputFieldName, DeployInputField.newBuilder().setName("someField").build()) .hasResultThat().isEqualTo(toSoyValue("input_someField")); assertFunctionCall(deployInputFieldName, "someField") .throwsException(ClassCastException.class); assertFunctionCall(deployInputFieldName, 13) .throwsException(ClassCastException.class); } @Test public void testFindInputsWithTestDefaultValues() { DeployInputField nonRequired = DeployInputField.newBuilder() .setRequired(false) .build(); IntegerBox intBoxWithDefaultValue = IntegerBox.newBuilder() .setDefaultValue(OptionalInt32.newBuilder().setValue(10).build()) .build(); DeployInputField requiredIntWithDefaultValue = DeployInputField.newBuilder() .setRequired(true) .setIntegerBox(intBoxWithDefaultValue) .build(); IntegerBox boxWithoutDefaultValue = IntegerBox.newBuilder() .setTestDefaultValue(OptionalInt32.newBuilder().setValue(10).build()) .build(); DeployInputField requiredWithoutDefaultValue = DeployInputField.newBuilder() .setRequired(true) .setName("TruePositive") .setIntegerBox(boxWithoutDefaultValue) .build(); StringBox boxWithDefaultValue = StringBox.newBuilder() .setDefaultValue("some default") .build(); DeployInputField requiredStringWithDefaultValue = DeployInputField.newBuilder() .setRequired(true) .setStringBox(boxWithDefaultValue) .build(); DeployInputSection section = DeployInputSection.newBuilder() .addFields(nonRequired) .addFields(requiredIntWithDefaultValue) .addFields(requiredStringWithDefaultValue) .addFields(requiredWithoutDefaultValue) .build(); DeployInputSpec spec = DeployInputSpec.newBuilder() .addSections(section) .build(); assertFunctionCall(findInputsWithTestDefaultValues, spec) .hasIterableResultThat().containsExactly(toSoyValue(requiredWithoutDefaultValue)); } @Test public void testFindInputTestDefaultValueForIntegerBox() { IntegerBox box = IntegerBox.newBuilder() .setTestDefaultValue(OptionalInt32.newBuilder().setValue(2).build()) .build(); DeployInputField field = DeployInputField.newBuilder() .setIntegerBox(box) .build(); assertFunctionCall(findInputTestDefaultValue, field) .hasResultThat().isEqualTo(toSoyValue(2)); } @Test public void testFindInputTestDefaultValueForStringBox() { StringBox box = StringBox.newBuilder() .setTestDefaultValue("my-value") .build(); DeployInputField field = DeployInputField.newBuilder() .setStringBox(box) .build(); assertFunctionCall(findInputTestDefaultValue, field) .hasResultThat().isEqualTo(toSoyValue("my-value")); } @Test public void testFindInputTestDefaultValueForUnsupportedInput() { BooleanCheckbox checkbox = BooleanCheckbox.newBuilder().getDefaultInstanceForType(); DeployInputField field = DeployInputField.newBuilder() .setBooleanCheckbox(checkbox) .build(); assertFunctionCall(findInputTestDefaultValue, field) .throwsException(IllegalArgumentException.class); } @Test public void testFindDeployInputField() { DeployInputField[] fields = { DeployInputField.newBuilder() .setName("field0") .setIntegerBox(IntegerBox.getDefaultInstance()) .build(), DeployInputField.newBuilder() .setName("field1") .setGroupedBooleanCheckbox(GroupedBooleanCheckbox.getDefaultInstance()) .build(), DeployInputField.newBuilder() .setName("field2") .setStringBox(StringBox.getDefaultInstance()) .build(), }; DeployInputSpec deployInputSpec = DeployInputSpec.newBuilder() .addSections( DeployInputSection.newBuilder() .addFields(fields[0]) .addFields(fields[1])) .addSections( DeployInputSection.newBuilder() .addFields(fields[2])) .build(); assertFunctionCall(findDeployInputField, "field0", deployInputSpec) .hasResultThat().isEqualTo(toSoyValue(fields[0])); assertFunctionCall(findDeployInputField, "field1", deployInputSpec) .hasResultThat().isEqualTo(toSoyValue(fields[1])); assertFunctionCall(findDeployInputField, "field2", deployInputSpec) .hasResultThat().isEqualTo(toSoyValue(fields[2])); assertFunctionCall(findDeployInputField, "field3", deployInputSpec) .throwsException(IllegalArgumentException.class); } @Test public void testFindDisplayGroup() { DisplayGroup displayGroup0 = DisplayGroup.newBuilder().setName("DISPLAY_GROUP0").build(); DisplayGroup displayGroup1 = DisplayGroup.newBuilder().setName("DISPLAY_GROUP1").build(); DeployInputSection.Builder sectionBuilder = DeployInputSection.newBuilder(); sectionBuilder .addFieldsBuilder() .setName("nonGroupedBooleanCheckboxField") .setIntegerBox(IntegerBox.getDefaultInstance()); sectionBuilder.addFieldsBuilder() .setName("group0LeadingField") .setGroupedBooleanCheckbox( GroupedBooleanCheckbox.newBuilder().setDisplayGroup(displayGroup0)); sectionBuilder .addFieldsBuilder() .setName("group0SecondField") .setGroupedBooleanCheckbox(GroupedBooleanCheckbox.getDefaultInstance()); sectionBuilder.addFieldsBuilder() .setName("group1LeadingField") .setGroupedBooleanCheckbox( GroupedBooleanCheckbox.newBuilder().setDisplayGroup(displayGroup1)); DeployInputSection section = sectionBuilder.build(); assertFunctionCall(findDisplayGroup, section.getFields(1), section) .hasResultThat().isEqualTo(toSoyValue(displayGroup0)); assertFunctionCall(findDisplayGroup, section.getFields(2), section) .hasResultThat().isEqualTo(toSoyValue(displayGroup0)); assertFunctionCall(findDisplayGroup, section.getFields(3), section) .hasResultThat().isEqualTo(toSoyValue(displayGroup1)); } @Test public void testFindDisplayGroup_noDisplayGroup() { DeployInputSection section = DeployInputSection.newBuilder() .addFields( DeployInputField.newBuilder() .setName("field0") .setGroupedBooleanCheckbox(GroupedBooleanCheckbox.getDefaultInstance())) .addFields( DeployInputField.newBuilder() .setName("field1") .setGroupedBooleanCheckbox(GroupedBooleanCheckbox.getDefaultInstance())) .build(); assertFunctionCall(findDisplayGroup, section.getFields(0), section) .throwsExceptionThat(RuntimeException.class) .hasMessageThat().startsWith("Unable to locate display group"); assertFunctionCall(findDisplayGroup, section.getFields(1), section) .throwsExceptionThat(RuntimeException.class) .hasMessageThat().startsWith("Unable to locate display group"); } @Test public void testFindDisplayGroup_precededByAnotherFieldType() { DeployInputSection section = DeployInputSection.newBuilder() .addFields( DeployInputField.newBuilder() .setName("field0") .setIntegerBox(IntegerBox.getDefaultInstance())) .addFields( DeployInputField.newBuilder() .setName("field1") .setGroupedBooleanCheckbox(GroupedBooleanCheckbox.getDefaultInstance())) .build(); assertFunctionCall(findDisplayGroup, section.getFields(1), section) .throwsExceptionThat(RuntimeException.class) .hasMessageThat().startsWith("No preceding grouped boolean checkbox field"); } @Test public void testFindVmTier_vmTierListAsSecondArg() { runTestFindVmTier(Functions.identity()); } @Test public void testFindVmTier_mutliVmSpecAsSecondArg() { runTestFindVmTier(new Function<List<VmTierSpec>, MultiVmDeploymentPackageSpec>() { @Override public MultiVmDeploymentPackageSpec apply(List<VmTierSpec> vmTiers) { return MultiVmDeploymentPackageSpec.newBuilder().addAllTiers(vmTiers).build(); } }); } private void runTestFindVmTier(Function<List<VmTierSpec>, ?> secondArgSupplier) { List<VmTierSpec> vmTiers = ImmutableList.of( VmTierSpec.newBuilder().setName("tier0").build(), VmTierSpec.newBuilder().setName("tier1").build()); Object secondArg = secondArgSupplier.apply(vmTiers); assertFunctionCall(findVmTier, "tier0", secondArg) .hasResultThat().isEqualTo(toSoyValue(vmTiers.get(0))); assertFunctionCall(findVmTier, "tier1", secondArg) .hasResultThat().isEqualTo(toSoyValue(vmTiers.get(1))); assertFunctionCall(findVmTier, "tier2", secondArg) .throwsExceptionThat(RuntimeException.class) .hasMessageThat().isEqualTo("Unable to locate tier with name tier2"); } @Test public void testFindVmTier_invalidSecondArg() { assertFunctionCall(findVmTier, "tier0", "tiers") .throwsExceptionThat(IllegalArgumentException.class) .hasMessageThat().startsWith("Unexpected 2nd arg type"); } @Test public void testTierPrefixed() { VmTierSpec tier = VmTierSpec.newBuilder().setName("mytier").build(); assertFunctionCall(tierPrefixed, "someProperty", (Object) null) .hasResultThat().isEqualTo(toSoyValue("someProperty")); assertFunctionCall(tierPrefixed, "someProperty", (Object) null, "-") .hasResultThat().isEqualTo(toSoyValue("someProperty")); assertFunctionCall(tierPrefixed, "someProperty", tier) .hasResultThat().isEqualTo(toSoyValue("mytier_someProperty")); assertFunctionCall(tierPrefixed, "someProperty", tier, "-") .hasResultThat().isEqualTo(toSoyValue("mytier-someProperty")); } @Test public void testExtractDeployInputFields() { DeployInputField domain = buildStringBoxInput("domain"); DeployInputField email = buildStringBoxInput("email"); DeployInputField username = buildStringBoxInput("username"); DeployInputField additionalDisks = buildIntegerBoxInput("additional-disks"); DeployInputSection mainSection = buildInputSection("Main", MAIN, domain); DeployInputSection userDataSection = buildInputSection("User data", MAIN, email, username); DeployInputSection otherSection = buildInputSection("Other", CUSTOM_BOTTOM, additionalDisks); DeployInputSpec inputSpec = DeployInputSpec.newBuilder() .addSections(mainSection) .addSections(userDataSection) .addSections(otherSection) .build(); List<SoyValue> allFields = ImmutableList.of( toSoyValue(domain), toSoyValue(email), toSoyValue(username), toSoyValue(additionalDisks)); assertFunctionCall(listDeployInputFields, inputSpec) .hasIterableResultThat().containsExactlyElementsIn(allFields); } @Test public void testFilterInputFieldsByTier() { DeployInputField email = buildStringBoxInput("email"); DeployInputField username = buildStringBoxInput("username"); DeployInputField additionalDisks = buildIntegerBoxInput("additional-disks"); DeployInputSection userDataSection = buildInputSection("User data", MAIN, email, username); DeployInputSection otherSection = buildInputSection("Other", CUSTOM_BOTTOM, additionalDisks); DeployInputSpec inputSpec = DeployInputSpec.newBuilder() .addSections(userDataSection) .addSections(otherSection) .build(); VmTierSpec vmTierSpec = VmTierSpec.newBuilder() .addGceMetadataItems( GceMetadataItem.newBuilder() .setKey("some-email") .setValueFromDeployInputField("email")) .addGceMetadataItems( GceMetadataItem.newBuilder() .setKey("disks-count") .setValueFromDeployInputField("additional-disks")) .build(); assertFunctionCall(listDeployInputFields, inputSpec, vmTierSpec) .hasIterableResultThat() .containsExactly(toSoyValue(email), toSoyValue(additionalDisks)); } @Test public void testBooleanExpressionDisplayConditionForDeployInputField() { BooleanDeployInputField field = BooleanDeployInputField.newBuilder() .setName("enableXYZ") .setNegated(true) .build(); BooleanExpression expression = BooleanExpression.newBuilder() .setBooleanDeployInputField(field) .build(); assertFunctionCall(booleanExpressionDisplayCondition, expression) .hasResultThat() .isEqualTo(StringData.forValue("!properties().input_enableXYZ")); } @Test public void testBooleanExpressionDisplayConditionForExternalIPAvailability_single() { BooleanExpression expression = BooleanExpression.newBuilder() .setHasExternalIp(ExternalIpAvailability.newBuilder().setNegated(true)) .build(); assertFunctionCall(booleanExpressionDisplayCondition, expression) .hasResultThat() .isEqualTo(StringData.forValue("properties().externalIP == \"NONE\"")); } @Test public void testBooleanExpressionDisplayConditionForMultipleParams() { BooleanExpression expression = BooleanExpression.newBuilder() .setHasExternalIp(ExternalIpAvailability.newBuilder().setNegated(false)) .setBooleanDeployInputField(BooleanDeployInputField.newBuilder() .setName("enableXYZ") .setNegated(true)) .build(); assertFunctionCall(booleanExpressionDisplayCondition, expression) .hasResultThat() .isEqualTo( StringData.forValue( "!properties().input_enableXYZ and properties().externalIP != \"NONE\"")); } @Test public void testBooleanExpressionDisplayConditionForExternalIPAvailability_multi() { ExternalIpAvailability externalIpAvailability = ExternalIpAvailability.newBuilder() .setTier("tier0") .setNegated(false) .build(); BooleanExpression expression = BooleanExpression.newBuilder() .setHasExternalIp(externalIpAvailability) .build(); List<VmTierSpec> tiersList = ImmutableList.of( VmTierSpec.newBuilder().setName("tier0").build(), VmTierSpec.newBuilder().setName("tier1").build() ); assertFunctionCall(booleanExpressionDisplayCondition, expression, tiersList) .hasResultThat() .isEqualTo(StringData.forValue("properties().tier0_externalIP != \"NONE\"")); } @Test public void testSolutionHasGpusWithNoGpuListMultiVm() { List<VmTierSpec> vmTiers = ImmutableList.of( VmTierSpec.newBuilder().setName("tier0").build(), VmTierSpec.newBuilder().setName("tier1").build()); MultiVmDeploymentPackageSpec spec = MultiVmDeploymentPackageSpec.newBuilder().addAllTiers(vmTiers).build(); assertFunctionCall(solutionHasGpus, spec).hasResultThat().isEqualTo(toSoyValue(false)); } @Test public void testSolutionHasGpusWithNoGpuListSingleVm() { SingleVmDeploymentPackageSpec spec = SingleVmDeploymentPackageSpec.newBuilder().getDefaultInstanceForType(); assertFunctionCall(solutionHasGpus, spec).hasResultThat().isEqualTo(toSoyValue(false)); } @Test public void testSolutionHasGpusWithGpuListMultiVm() { List<String> types = Arrays.asList("nvidia-tesla-p100"); AcceleratorSpec acceleratorSpec = AcceleratorSpec.newBuilder().addAllTypes(types).build(); List<VmTierSpec> vmTiers = ImmutableList.of( VmTierSpec.newBuilder().setName("tier0").addAccelerators(acceleratorSpec).build(), VmTierSpec.newBuilder().setName("tier1").build()); MultiVmDeploymentPackageSpec spec = MultiVmDeploymentPackageSpec.newBuilder().addAllTiers(vmTiers).build(); assertFunctionCall(solutionHasGpus, spec).hasResultThat().isEqualTo(toSoyValue(true)); } @Test public void testSolutionHasGpusWithGpuListSingleVm() { List<String> types = Arrays.asList("nvidia-tesla-p100"); AcceleratorSpec acceleratorSpec = AcceleratorSpec.newBuilder().addAllTypes(types).build(); SingleVmDeploymentPackageSpec spec = SingleVmDeploymentPackageSpec.newBuilder().addAccelerators(acceleratorSpec).build(); assertFunctionCall(solutionHasGpus, spec).hasResultThat().isEqualTo(toSoyValue(true)); } private DeployInputField buildStringBoxInput(String fieldName) { return DeployInputField.newBuilder() .setName(fieldName) .setStringBox(StringBox.getDefaultInstance()) .build(); } private DeployInputField buildIntegerBoxInput(String fieldName) { return DeployInputField.newBuilder() .setName(fieldName) .setIntegerBox(IntegerBox.getDefaultInstance()) .build(); } private DeployInputSection buildInputSection( String name, Placement placement, DeployInputField ... fields) { return DeployInputSection.newBuilder() .setName(name) .setPlacement(placement) .addAllFields(ImmutableList.copyOf(fields)) .build(); } private class ResultAssert { private final Callable<SoyValue> callable; ResultAssert(Callable<SoyValue> callable) { this.callable = callable; } @CheckReturnValue ThrowableSubject throwsExceptionThat(Class<? extends Throwable> throwableClass) { try { callable.call(); } catch (Throwable throwable) { assertWithMessage("Expected exception of type " + throwableClass.getName()) .that(throwable).isInstanceOf(throwableClass); return assertThat(throwable); } fail("Should have thrown exception of type " + throwableClass.getName()); return null; } void throwsException(Class<? extends Throwable> throwableClass) { throwsExceptionThat(throwableClass).isNotNull(); } @CheckReturnValue Subject hasResultThat() { try { return assertThat(callable.call()); } catch (Exception e) { throw new AssertionError("Unexpected exception", e); } } @CheckReturnValue IterableSubject hasIterableResultThat() { try { return assertThat(((SoyList) callable.call()).asResolvedJavaList()); } catch (Exception e) { throw new AssertionError("Unexpected exception", e); } } } private ResultAssert assertFunctionCall(final SoyJavaFunction function, final Object... args) { return new ResultAssert( new Callable<SoyValue>() { @Override public SoyValue call() throws Exception { ImmutableList.Builder<SoyValue> argsData = ImmutableList.builder(); for (Object arg : args) { argsData.add(SoyValueConverter.INSTANCE.convert(arg).resolve()); } return function.computeForJava(argsData.build()); } }); } private SoyValue toSoyValue(Object displayGroup0) { return SoyValueConverter.INSTANCE.convert(displayGroup0).resolve(); } }