<commit_before>/*
 * Copyright 2019, TeamDev. All rights reserved.
 *
 * 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.protoc;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.DescriptorProtos;
import com.google.protobuf.compiler.PluginProtos;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
import io.spine.code.proto.MessageType;
import io.spine.option.OptionExtensionRegistry;
import io.spine.option.OptionsProto;
import io.spine.protoc.MethodBody;
import io.spine.protoc.MethodFactory;
import io.spine.tools.gradle.compiler.protoc.GeneratedInterfaces;
import io.spine.tools.gradle.compiler.protoc.GeneratedMethods;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Base64;
import java.util.List;

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

@DisplayName("Plugin should")
final class PluginTest {

    private static final String TEST_PROTO_POSTFIX = "_generators.proto";
    private static final String TEST_PROTO_FILE = "spine/tools/protoc/test_generators.proto";

    @DisplayName("process code generation request")
    @Test
    void processCodeGenerationRequest() {
        GeneratedInterfaces interfaces = GeneratedInterfaces.withDefaults();
        interfaces.filePattern().endsWith(TEST_PROTO_POSTFIX)
                  .markWith(TestInterface.class.getName());
        GeneratedMethods methods = GeneratedMethods.withDefaults();
        methods.filePattern().endsWith(TEST_PROTO_POSTFIX)
               .withMethodFactory(TestMethodFactory.class.getName());
        CodeGeneratorRequest request = requestBuilder()
                .addProtoFile(TestGeneratorsProto.getDescriptor()
                                                 .toProto())
                .addFileToGenerate(TEST_PROTO_FILE)
                .setParameter(encodedProtocConfig(interfaces, methods))
                .build();

        CodeGeneratorResponse response = runPlugin(request);

        assertEquals(2, response.getFileCount());
        CodeGeneratorResponse.File messageInterface = response.getFile(0);
        CodeGeneratorResponse.File messageMethod = response.getFile(1);
        assertEquals(TestInterface.class.getName() + ',', messageInterface.getContent());
        assertEquals(TestMethodFactory.TEST_METHOD.value(), messageMethod.getContent());
    }

    private static String encodedProtocConfig(GeneratedInterfaces interfaces,
                                              GeneratedMethods methods) {
        SpineProtocConfig protocConfig = SpineProtocConfig
                .newBuilder()
                .setGeneratedInterfaces(interfaces.asProtocConfig())
                .setGeneratedMethods(methods.asProtocConfig())
                .build();
        return Base64.getEncoder()
                     .encodeToString(protocConfig.toByteArray());
    }

    private static CodeGeneratorResponse runPlugin(CodeGeneratorRequest request) {
        try (InputStream testInput = new ByteArrayInputStream(request.toByteArray());
             ByteArrayOutputStream bos = new ByteArrayOutputStream();
             PrintStream testOutput = new PrintStream(bos)
        ) {
            //noinspection ZeroLengthArrayAllocation
            withSystemStreams(testInput, testOutput, () -> Plugin.main(new String[]{}));
            return CodeGeneratorResponse.parseFrom(bos.toByteArray(),
                                                   OptionExtensionRegistry.instance());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }<commit_msg>Add test for the defaults override functionality<commit_after>/*
 * Copyright 2019, TeamDev. All rights reserved.
 *
 * 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.protoc;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.DescriptorProtos;
import com.google.protobuf.compiler.PluginProtos;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest;
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
import io.spine.code.proto.MessageType;
import io.spine.option.OptionExtensionRegistry;
import io.spine.option.OptionsProto;
import io.spine.protoc.MethodBody;
import io.spine.protoc.MethodFactory;
import io.spine.tools.gradle.compiler.protoc.GeneratedInterfaces;
import io.spine.tools.gradle.compiler.protoc.GeneratedMethods;
import io.spine.tools.protoc.messageinterface.TestEventsProto;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Base64;
import java.util.List;

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

@DisplayName("Plugin should")
final class PluginTest {

    private static final String TEST_PROTO_POSTFIX = "_generators.proto";
    private static final String TEST_PROTO_FILE = "spine/tools/protoc/test_generators.proto";

    @DisplayName("process code generation request")
    @Test
    void processCodeGenerationRequest() {
        GeneratedInterfaces interfaces = GeneratedInterfaces.withDefaults();
        interfaces.filePattern()
                  .endsWith(TEST_PROTO_POSTFIX)
                  .markWith(TestInterface.class.getName());
        GeneratedMethods methods = GeneratedMethods.withDefaults();
        methods.filePattern()
               .endsWith(TEST_PROTO_POSTFIX)
               .withMethodFactory(TestMethodFactory.class.getName());
        CodeGeneratorRequest request = requestBuilder()
                .addProtoFile(TestGeneratorsProto.getDescriptor()
                                                 .toProto())
                .addFileToGenerate(TEST_PROTO_FILE)
                .setParameter(encodedProtocConfig(interfaces, methods))
                .build();

        CodeGeneratorResponse response = runPlugin(request);

        assertEquals(2, response.getFileCount());
        CodeGeneratorResponse.File messageInterface = response.getFile(0);
        CodeGeneratorResponse.File messageMethod = response.getFile(1);
        assertEquals(TestInterface.class.getName() + ',', messageInterface.getContent());
        assertEquals(TestMethodFactory.TEST_METHOD.value(), messageMethod.getContent());
    }

    @DisplayName("skip generation of standard interfaces if they are `ignored`")
    @Test
    void skipStandardInterfacesIfIgnored() {
        GeneratedInterfaces interfaces = GeneratedInterfaces.withDefaults();
        interfaces.filePattern()
                  .endsWith("events.proto")
                  .ignore();
        CodeGeneratorRequest request = requestBuilder()
                .addProtoFile(TestEventsProto.getDescriptor()
                                             .toProto())
                .addFileToGenerate("spine/tools/protoc/messageinterface/test_events.proto")
                .setParameter(encodedProtocConfig(interfaces))
                .build();
        CodeGeneratorResponse response = runPlugin(request);

        assertEquals(0, response.getFileCount());
    }

    private static String encodedProtocConfig(GeneratedInterfaces interfaces) {
        return encodedProtocConfig(interfaces, GeneratedMethods.withDefaults());
    }

    private static String encodedProtocConfig(GeneratedInterfaces interfaces,
                                              GeneratedMethods methods) {
        SpineProtocConfig protocConfig = SpineProtocConfig
                .newBuilder()
                .setGeneratedInterfaces(interfaces.asProtocConfig())
                .setGeneratedMethods(methods.asProtocConfig())
                .build();
        return Base64.getEncoder()
                     .encodeToString(protocConfig.toByteArray());
    }

    private static CodeGeneratorResponse runPlugin(CodeGeneratorRequest request) {
        try (InputStream testInput = new ByteArrayInputStream(request.toByteArray());
             ByteArrayOutputStream bos = new ByteArrayOutputStream();
             PrintStream testOutput = new PrintStream(bos)
        ) {
            //noinspection ZeroLengthArrayAllocation
            withSystemStreams(testInput, testOutput, () -> Plugin.main(new String[]{}));
            return CodeGeneratorResponse.parseFrom(bos.toByteArray(),
                                                   OptionExtensionRegistry.instance());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
{'fraction_non_alphanumeric': 0.0827799083341128, 'fraction_numerical': 0.0021513422504910672, 'mean_word_length': 3.2344554455445547, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3524473', 'n_tokens_mistral': 2733, 'n_tokens_neox': 2530, 'n_words': 653}