package com.atlassian.bitbucket.mesh.process;

import com.atlassian.bitbucket.mesh.process.handler.AbstractLineStdioHandler;
import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.HashMap;
import java.util.Map;

@RunWith(MockitoJUnitRunner.class)
public class ProcessParametersTest {

    @Mock
    private ProcessCompletionHandler completionHandler;
    @Mock
    private AbstractLineStdioHandler<Integer> stdioHandler;
    @Rule
    public final ExpectedException thrown = ExpectedException.none();

    @Test
    public void testArgumentParsingWithNullByteInList() {
        String argumentWithNull = "aaaa\000--bad";

        String exceptionMessage = "Unsupported \\0 character detected: " + argumentWithNull;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .arguments(ImmutableList.of("git", "foo", "-bar", argumentWithNull))
                .build();
    }

    @Test
    public void testArgumentParsingWithNullInByteValue() {
        String argumentWithNull = "git foo -bar aaaa\000--bad";

        String exceptionMessage = "Unsupported \\0 character detected: " + argumentWithNull;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .arguments(argumentWithNull)
                .build();
    }

    @Test
    public void testArgumentParsingWithNullByteInValues() {
        String argumentWithNull = "aaaa\000--bad";

        String exceptionMessage = "Unsupported \\0 character detected: " + argumentWithNull;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .arguments("git", "foo", "-bar", argumentWithNull)
                .build();
    }

    @Test
    public void testEnvironmentParsingBlankKey() {
        String exceptionMessage = "A non-blank key is required";

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .environment("", "value")
                .build();
    }

    @Test
    public void testEnvironmentParsingNullByteInMap() {
        Map<String, String> map = new HashMap<>();
        String valueWithNull = "a\000b";
        map.put("key", valueWithNull);
        String exceptionMessage = "Unsupported \\0 character detected: " + valueWithNull;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .environment(map)
                .build();
    }

    @Test
    public void testEnvironmentParsingNullByteInValue() {
        String valueWithNull = "a\000b";
        String exceptionMessage = "Unsupported \\0 character detected: " + valueWithNull;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .environment("key", valueWithNull)
                .build();
    }

    @Test
    public void testEnvironmentParsingNullByteInKeyViaMutation() {
        String keyWithNull = "a\0b";
        String exceptionMessage = "Unsupported \\0 character detected: " + keyWithNull;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        ProcessParameters<Integer> params = new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .build();
        params.environmentPutIfAbsent(keyWithNull, "value");
    }

    @Test
    public void testEnvironmentParsingNullByteInValueViaMutation() {
        String valueWithNull = "a\0b";
        String exceptionMessage = "Unsupported \\0 character detected: " + valueWithNull;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(exceptionMessage);

        ProcessParameters<Integer> params = new ProcessParameters.Builder<>(stdioHandler, completionHandler)
                .build();
        params.environmentPutIfAbsent("key", valueWithNull);
    }
}