<commit_before>/*
 * Copyright 2021, TeamDev. All rights reserved.
 *
 * 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
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.tools.mc.java.protoc.message;

import com.google.common.testing.NullPointerTester;
import com.google.common.truth.IterableSubject;
import com.google.common.truth.StringSubject;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse.File;
import com.google.protobuf.compiler.PluginProtos.Version;
import io.spine.base.CommandMessage;
import io.spine.base.EventMessage;
import io.spine.base.RejectionMessage;
import io.spine.base.UuidValue;
import io.spine.code.java.PackageName;
import io.spine.tools.java.fs.Directory;
import io.spine.tools.java.fs.FileName;
import io.spine.tools.java.fs.SourceFile;
import io.spine.tools.mc.java.protoc.CodeGenerator;
import io.spine.tools.protoc.SpineProtocConfig;
import io.spine.tools.protoc.plugin.message.tests.EveryIsGeneratedProto;
import io.spine.tools.protoc.plugin.message.tests.EveryIsInOneFileProto;
import io.spine.tools.protoc.plugin.message.tests.EveryIsTestProto;
import io.spine.tools.protoc.plugin.message.tests.IsGeneratedProto;
import io.spine.tools.protoc.plugin.message.tests.IsInOneFileProto;
import io.spine.tools.protoc.plugin.message.tests.IsTestProto;
import io.spine.tools.protoc.plugin.message.tests.NonUuidValues;
import io.spine.tools.protoc.plugin.message.tests.Rejections;
import io.spine.tools.protoc.plugin.message.tests.TestCommandsProto;
import io.spine.tools.protoc.plugin.message.tests.TestEventsProto;
import io.spine.tools.protoc.plugin.message.tests.UserNameProto;
import io.spine.tools.protoc.plugin.message.tests.UserProto;
import io.spine.tools.protoc.plugin.message.tests.UuidValues;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.google.common.truth.Truth.assertThat;
import static io.spine.testing.Assertions.assertIllegalArgument;
import static java.lang.String.format;
import static java.util.regex.Pattern.compile;
import static java.util.stream.Collectors.toSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

@DisplayName("`InterfaceGen` should")
final class InterfaceGenTest {

    private static final String INSERTION_POINT_IMPLEMENTS = "message_implements:%s";

    private static final String PROTO_PACKAGE = "spine.tools.protoc.msg";
    private static final String PROTO_DIR = PROTO_PACKAGE.replace('.', '/');

    /**
     * The package name of the test data, as declared in proto files under
     * the {@code proto/spine/tools/protoc/msg} directory.
     */
    private static final PackageName JAVA_PACKAGE =
            PackageName.of("io.spine.tools.protoc.plugin.message.tests");

    /**
     * The directory name containing the code generated from proto test data from
     * the {@code proto/spine/tools/protoc/msg} directory.
     *
     * @see #JAVA_PACKAGE
     */
    private static final String JAVA_DIR = JAVA_PACKAGE.value().replace('.', '/');

    /**
     * The pattern for the detecting {@linkplain #JAVA_PACKAGE test data package}.
     */
    @SuppressWarnings("DynamicRegexReplaceableByCompiledPattern")
    private static final String PACKAGE_PATTERN =
            "^\\s*" + JAVA_PACKAGE.value().replace(".", "\\.");

    private static final Pattern CUSTOMER_EVENT_INTERFACE_PATTERN =
            compile(PACKAGE_PATTERN + "\\.ProtocCustomerEvent\\s*,\\s*$");

    private static final Pattern PROJECT_EVENT_INTERFACE_PATTERN =
            compile(PACKAGE_PATTERN + "\\.ProtocProjectEvent\\s*,\\s*$");

    private static final Pattern PROJECT_EVENT_INTERFACE_DECL_PATTERN =
            compile("public\\s+interface\\s+ProtocProjectEvent\\s*extends\\s+Message\\s*\\{\\s*}");

    private static final Pattern CUSTOMER_EVENT_OR_COMMAND =
            compile("Customer(Command|Event)");

    private CodeGenerator codeGenerator;

    private static String protoFile(String shortName) {
        return PROTO_DIR + '/' + shortName;
    }

    private static String javaFile(String shortName) {
        return JAVA_DIR + '/' + shortName;
    }

    private static Version version() {
        return Version.newBuilder()
                      .setMajor(3)
                      .setMinor(6)
                      .setPatch(1)
                      .build();
    }

    @BeforeEach
    void setUp() {
        // TODO:2021-06-29:dmytro.dashenkov: Add interfaces.
        SpineProtocConfig config = SpineProtocConfig
                .newBuilder()
                .build();
        codeGenerator = InterfaceGen.instance(config);
    }

    @Test
    @DisplayName("not accept nulls")
    void notAcceptNulls() {
        new NullPointerTester()
                .setDefault(CodeGeneratorRequest.class, CodeGeneratorRequest.getDefaultInstance())
                .testAllPublicStaticMethods(InterfaceGen.class);
    }

    private static String messageNameFrom(File file) {
        String fileName = file.getName();
        String messageName = PROTO_PACKAGE + '.' +
                fileName.substring(fileName.lastIndexOf('/') + 1, fileName.lastIndexOf('.'));
        return messageName;
    }

    @Nested
    @DisplayName("generate insertion point contents for")
    class InsertionPoints {

        @Test
        @DisplayName("`EveryIs` option")
        void everyIsOption() {
            String filePath = protoFile("every_is_test.proto");

            FileDescriptorProto fileDescr =<commit_msg>Add default values for test inputs instead of empty config<commit_after>/*
 * Copyright 2021, TeamDev. All rights reserved.
 *
 * 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
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.tools.mc.java.protoc.message;

import com.google.common.testing.NullPointerTester;
import com.google.common.truth.IterableSubject;
import com.google.common.truth.StringSubject;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse.File;
import com.google.protobuf.compiler.PluginProtos.Version;
import io.spine.base.CommandMessage;
import io.spine.base.EventMessage;
import io.spine.base.RejectionMessage;
import io.spine.base.UuidValue;
import io.spine.code.java.PackageName;
import io.spine.tools.java.fs.Directory;
import io.spine.tools.java.fs.FileName;
import io.spine.tools.java.fs.SourceFile;
import io.spine.tools.mc.java.codegen.Codegen;
import io.spine.tools.mc.java.protoc.CodeGenerator;
import io.spine.tools.protoc.SpineProtocConfig;
import io.spine.tools.protoc.plugin.message.tests.EveryIsGeneratedProto;
import io.spine.tools.protoc.plugin.message.tests.EveryIsInOneFileProto;
import io.spine.tools.protoc.plugin.message.tests.EveryIsTestProto;
import io.spine.tools.protoc.plugin.message.tests.IsGeneratedProto;
import io.spine.tools.protoc.plugin.message.tests.IsInOneFileProto;
import io.spine.tools.protoc.plugin.message.tests.IsTestProto;
import io.spine.tools.protoc.plugin.message.tests.NonUuidValues;
import io.spine.tools.protoc.plugin.message.tests.Rejections;
import io.spine.tools.protoc.plugin.message.tests.TestCommandsProto;
import io.spine.tools.protoc.plugin.message.tests.TestEventsProto;
import io.spine.tools.protoc.plugin.message.tests.UserNameProto;
import io.spine.tools.protoc.plugin.message.tests.UserProto;
import io.spine.tools.protoc.plugin.message.tests.UuidValues;
import org.gradle.api.Project;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.google.common.truth.Truth.assertThat;
import static io.spine.testing.Assertions.assertIllegalArgument;
import static java.lang.String.format;
import static java.util.regex.Pattern.compile;
import static java.util.stream.Collectors.toSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

@DisplayName("`InterfaceGen` should")
final class InterfaceGenTest {

    private static final String INSERTION_POINT_IMPLEMENTS = "message_implements:%s";

    private static final String PROTO_PACKAGE = "spine.tools.protoc.msg";
    private static final String PROTO_DIR = PROTO_PACKAGE.replace('.', '/');

    /**
     * The package name of the test data, as declared in proto files under
     * the {@code proto/spine/tools/protoc/msg} directory.
     */
    private static final PackageName JAVA_PACKAGE =
            PackageName.of("io.spine.tools.protoc.plugin.message.tests");

    /**
     * The directory name containing the code generated from proto test data from
     * the {@code proto/spine/tools/protoc/msg} directory.
     *
     * @see #JAVA_PACKAGE
     */
    private static final String JAVA_DIR = JAVA_PACKAGE.value().replace('.', '/');

    /**
     * The pattern for the detecting {@linkplain #JAVA_PACKAGE test data package}.
     */
    @SuppressWarnings("DynamicRegexReplaceableByCompiledPattern")
    private static final String PACKAGE_PATTERN =
            "^\\s*" + JAVA_PACKAGE.value().replace(".", "\\.");

    private static final Pattern CUSTOMER_EVENT_INTERFACE_PATTERN =
            compile(PACKAGE_PATTERN + "\\.ProtocCustomerEvent\\s*,\\s*$");

    private static final Pattern PROJECT_EVENT_INTERFACE_PATTERN =
            compile(PACKAGE_PATTERN + "\\.ProtocProjectEvent\\s*,\\s*$");

    private static final Pattern PROJECT_EVENT_INTERFACE_DECL_PATTERN =
            compile("public\\s+interface\\s+ProtocProjectEvent\\s*extends\\s+Message\\s*\\{\\s*}");

    private static final Pattern CUSTOMER_EVENT_OR_COMMAND =
            compile("Customer(Command|Event)");

    private CodeGenerator codeGenerator;

    private static String protoFile(String shortName) {
        return PROTO_DIR + '/' + shortName;
    }

    private static String javaFile(String shortName) {
        return JAVA_DIR + '/' + shortName;
    }

    private static Version version() {
        return Version.newBuilder()
                      .setMajor(3)
                      .setMinor(6)
                      .setPatch(1)
                      .build();
    }

    private static SpineProtocConfig config = SpineProtocConfig.getDefaultInstance();

    @BeforeAll
    static void setUpConfig() {
        Project project = ProjectBuilder.builder().build();
        Codegen codegen = new Codegen(project);
        config = codegen.toProto();
    }

    @BeforeEach
    void setUp() {
        codeGenerator = InterfaceGen.instance(config);
    }

    @Test
    @DisplayName("not accept nulls")
    void notAcceptNulls() {
        new NullPointerTester()
                .setDefault(CodeGeneratorRequest.class, CodeGeneratorRequest.getDefaultInstance())
                .testAllPublicStaticMethods(InterfaceGen.class);
    }

    private static String messageNameFrom(File file) {
        String fileName = file.getName();
        String messageName = PROTO_PACKAGE + '.' +
                fileName.substring(fileName.lastIndexOf('/') + 1, fileName.lastIndexOf('.'));
        return messageName;
    }

    @Nested
    @DisplayName("generate insertion point contents for")
    class InsertionPoints {

        @Test
        @DisplayName("`EveryIs` option")
        void everyIsOption() {
            String filePath = protoFile("every_is_test.proto");

            FileDescriptorProto fileDescr =
{'fraction_non_alphanumeric': 0.10264427979063286, 'fraction_numerical': 0.00217524301543063, 'mean_word_length': 3.7366387636831937, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '145309', 'n_tokens_mistral': 4397, 'n_tokens_neox': 4186, 'n_words': 1003}