Skip to content

Commit

Permalink
chore(crd-generator): Add approval tests for crd-generator
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo42 committed Apr 23, 2024
1 parent b8eeca4 commit 01dafb2
Show file tree
Hide file tree
Showing 14 changed files with 777 additions and 5 deletions.
7 changes: 6 additions & 1 deletion crd-generator/api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<artifactId>kubernetes-client-api</artifactId>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jsonSchema</artifactId>
Expand Down Expand Up @@ -82,6 +82,11 @@
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.approvaltests</groupId>
<artifactId>approvaltests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,19 @@
import io.fabric8.kubernetes.model.annotation.Version;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static io.fabric8.crd.generator.CRDGeneratorAssertions.assertCRDOutputEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* Use Approval tests, see package example
*/
@Deprecated
class CRDGeneratorExamplesTest {

protected boolean parallelCRDGeneration;

@Test
void multiple() throws IOException {
void multiple() {
assertCRDOutputEquals(newCRDGenerator(),
io.fabric8.crd.example.multiple.v1.Multiple.class, io.fabric8.crd.example.multiple.v2.Multiple.class);
}
Expand All @@ -50,7 +52,7 @@ void multipleStorage_thenFail() {
}

@Test
void k8sValidation() throws IOException {
void k8sValidation() {
assertCRDOutputEquals(newCRDGenerator(), K8sValidation.class);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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 io.fabric8.crd.generator;

import io.fabric8.crd.example.multiple.v2.MultipleSpec;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Version;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.io.File;

import static org.junit.jupiter.api.Assertions.assertThrows;

class MultipleStoredVersionsTest {

@Group("sample.fabric8.io")
@Version(value = "v3")
public static class Multiple extends CustomResource<MultipleSpec, Void> {
}

@Test
void generateV1_expectException(@TempDir File tmpDir) {
test("v1", false, tmpDir);
}

@Test
void generateV1beta1_expectException(@TempDir File tmpDir) {
test("v1beta1", false, tmpDir);
}

@Test
void generateV1Parallel_expectException(@TempDir File tmpDir) {
test("v1", true, tmpDir);
}

@Test
void generateV1beta1Parallel_expectException(@TempDir File tmpDir) {
test("v1beta1", true, tmpDir);
}

private void test(String crdVersion, boolean parallel, File tmpDir) {
final CRDGenerator crdGenerator = new CRDGenerator()
.inOutputDir(tmpDir)
.withParallelGenerationEnabled(parallel)
.forCRDVersions(crdVersion)
.customResourceClasses(io.fabric8.crd.example.multiple.v2.Multiple.class, Multiple.class);

assertThrows(IllegalStateException.class, crdGenerator::generate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
package io.fabric8.crd.generator;

/**
* Use Approval tests, see package example
*/
@Deprecated
public class ParallelCRDGeneratorExamplesTest extends CRDGeneratorExamplesTest {
public ParallelCRDGeneratorExamplesTest() {
parallelCRDGeneration = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package io.fabric8.crd.generator.example;

/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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.
*/

import io.fabric8.crd.generator.CRDGenerationInfo;
import io.fabric8.crd.generator.CRDGenerator;
import io.fabric8.crd.generator.CRDInfo;
import io.fabric8.kubernetes.client.CustomResource;
import org.approvaltests.Approvals;
import org.approvaltests.approvers.ApprovalApprover;
import org.approvaltests.approvers.FileApprover;
import org.approvaltests.core.Options;
import org.approvaltests.namer.ApprovalNamer;
import org.approvaltests.writers.ApprovalTextWriter;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class AbstractCRDGeneratorApprovalTest {

private static final String[] CRD_VERSIONS = new String[] {
"v1", "v1beta1"
};

protected abstract Class<? extends CustomResource<?, ?>>[] crClasses();

protected abstract String[] expectedCRDs();

@BeforeAll
public void init() {
// Allow using the same approval files for this class multiple times (required for parallel testing)
String className = getClass().getName().replace('.', File.separatorChar);
FileApprover.tracker.addAllowedDuplicates(f -> f.contains(className));
}

@Test
public void test() {
test(false);
}

@Test
public void testParallel() {
test(true);
}

public void test(boolean parallel) {
Class<? extends CustomResource<?, ?>>[] crClasses = crClasses();
assertNotNull(crClasses);
assertTrue(crClasses.length > 0);

final File outputDir;
try {
outputDir = Files.createTempDirectory("crd-").toFile();
} catch (IOException e) {
fail("Could not create temp directory", e);
throw new RuntimeException(e);
}

// generate actual CRDs
final CRDGenerationInfo crdGenerationInfo = new CRDGenerator()
.withParallelGenerationEnabled(parallel)
.inOutputDir(outputDir)
.customResourceClasses(crClasses)
.forCRDVersions(CRD_VERSIONS)
.detailedGenerate();

for (String crdName : expectedCRDs()) {
Map<String, CRDInfo> crdInfos = crdGenerationInfo.getCRDInfos(crdName);
assertNotNull(crdInfos, "Could not find expected CRD " + crdName + " in results");
for (String crdVersion : CRD_VERSIONS) {
CRDInfo crdInfo = crdInfos.get(crdVersion);
final File actualCRDFile = new File(crdInfo.getFilePath());
String crdFileContent = readFile(actualCRDFile);
verify(crdName, crdVersion, crdFileContent);
}
}

// only delete the generated files if the test is successful
deleteDirectory(outputDir);
}

private void verify(String crdName, String crdVersion, String crdFileContent) {
ApprovalTextWriter writer = new ApprovalTextWriter(crdFileContent, new Options()
.forFile().withExtension(".yml"));
ApprovalNamer approvalNamer = new CRDGeneratorApprovalNamer(AbstractCRDGeneratorApprovalTest.class, getClass())
.addAdditionalInformation(crdName)
.addAdditionalInformation(crdVersion);
ApprovalApprover approver = new FileApprover(writer, approvalNamer);
Approvals.verify(approver);
}

private String readFile(File file) {
try {
return new BufferedReader(new InputStreamReader(Files.newInputStream(file.toPath())))
.lines().collect(Collectors.joining("\n"));
} catch (IOException e) {
fail(e);
throw new RuntimeException(e);
}
}

private void deleteDirectory(File dir) {
try (Stream<Path> fileStream = Files.walk(dir.toPath())) {
fileStream.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
} catch (IOException e) {
fail("Could not delete output directory", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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 io.fabric8.crd.generator.example;

import com.spun.util.tests.StackTraceReflectionResult;
import com.spun.util.tests.TestUtils;
import org.approvaltests.namer.ApprovalNamer;
import org.approvaltests.namer.AttributeStackSelector;
import org.approvaltests.namer.NamerFactory;
import org.approvaltests.writers.Writer;

import java.io.File;

class CRDGeneratorApprovalNamer implements ApprovalNamer {

private final String implementationClassName;
private final String baseDirectory;
private final String additionalInformation;

public CRDGeneratorApprovalNamer(Class<?> abstractClass, Class<?> implementationClass) {
StackTraceReflectionResult info = TestUtils.getCurrentFileForMethod(new AttributeStackSelector());
additionalInformation = NamerFactory.getAndClearAdditionalInformation();

String abstractClassPath = abstractClass.getPackage().getName().replace('.', File.separatorChar);
String implementationClassPath = implementationClass.getPackage().getName().replace('.', File.separatorChar);
this.implementationClassName = implementationClass.getSimpleName();

String abstractClassAbsolutePath = info.getSourceFile().getAbsolutePath();
this.baseDirectory = abstractClassAbsolutePath.replace(abstractClassPath,
File.separatorChar + implementationClassPath);
}

public CRDGeneratorApprovalNamer(String baseDirectory,
String implementationClassName,
String additionalInformation) {
this.baseDirectory = baseDirectory;
this.implementationClassName = implementationClassName;
this.additionalInformation = additionalInformation;
}

@Override
public String getApprovalName() {
return String.format("%s%s", implementationClassName, additionalInformation);
}

@Override
public String getSourceFilePath() {
String sub = NamerFactory.getSubdirectory();
String subdirectory = sub != null && !sub.isEmpty() ? sub + File.separator : "";
return baseDirectory + File.separator + subdirectory;
}

@Override
public File getReceivedFile(String extensionWithDot) {
return new File(
getSourceFilePath() + File.separatorChar + getApprovalName() + Writer.received + extensionWithDot);
}

@Override
public File getApprovedFile(String extensionWithDot) {
return new File(
getSourceFilePath() + File.separatorChar + getApprovalName() + Writer.approved + extensionWithDot);
}

public ApprovalNamer addAdditionalInformation(String additionalInformation) {
return new CRDGeneratorApprovalNamer(this.baseDirectory, this.implementationClassName,
this.additionalInformation + "." + additionalInformation);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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 io.fabric8.crd.generator.example;

import io.fabric8.kubernetes.client.CustomResource;

class K8sValidationTest extends AbstractCRDGeneratorApprovalTest {

protected Class<? extends CustomResource<?, ?>>[] crClasses() {
return new Class[] {
io.fabric8.crd.example.k8svalidation.K8sValidation.class
};
}

protected String[] expectedCRDs() {
return new String[] {
"k8svalidations.samples.fabric8.io"
};
}
}
Loading

0 comments on commit 01dafb2

Please sign in to comment.