/*
 * Copyright 2021 ThoughtWorks, 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 com.thoughtworks.go.server.newsecurity.filterchains;

import ch.qos.logback.core.util.FileSize;
import com.thoughtworks.go.http.mocks.HttpRequestBuilder;
import com.thoughtworks.go.http.mocks.MockHttpServletRequest;
import com.thoughtworks.go.http.mocks.MockHttpServletResponse;
import com.thoughtworks.go.server.newsecurity.filters.ArtifactSizeEnforcementFilter;
import com.thoughtworks.go.server.service.ArtifactsDirHolder;
import com.thoughtworks.go.server.service.GoConfigService;
import com.thoughtworks.go.util.SystemEnvironment;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;

import static com.thoughtworks.go.http.mocks.MockHttpServletResponseAssert.assertThat;
import static com.thoughtworks.go.server.newsecurity.filterchains.DenyGoCDAccessForArtifactsFilterChainTest.wrap;
import static org.mockito.Mockito.*;

class ArtifactSizeEnforcementFilterChainTest {

    private File artifactsDir;

    private MockHttpServletRequest request;
    private MockHttpServletResponse response;
    private ArtifactSizeEnforcementFilterChain filter;
    private FilterChain filterChain;

    @BeforeEach
    void setUp() {
        artifactsDir = spy(new File("."));
        when(artifactsDir.getUsableSpace()).thenReturn(FileSize.valueOf("1GB").getSize());
        GoConfigService goConfigService = mock(GoConfigService.class);
        when(goConfigService.artifactsDir()).thenReturn(artifactsDir);

        response = new MockHttpServletResponse();
        ArtifactsDirHolder artifactsDirHolder = new ArtifactsDirHolder(null, goConfigService);
        artifactsDirHolder.initialize();
        filter = new ArtifactSizeEnforcementFilterChain(new ArtifactSizeEnforcementFilter(artifactsDirHolder, new SystemEnvironment()));
        filterChain = mock(FilterChain.class);
    }

    @ParameterizedTest
    @ValueSource(strings = {"/files/bar/foo.zip", "/remoting/files/bar/foo.zip"})
    void shouldDoNothingWhenNoArtifactSizeHeaderPresent(String path) throws IOException, ServletException {
        request = HttpRequestBuilder.POST(path).build();
        filter.doFilter(request, response, filterChain);

        assertThat(response)
                .isOk();

        verify(filterChain).doFilter(wrap(request), wrap(response));
    }

    @ParameterizedTest
    @ValueSource(strings = {"/files/bar/foo.zip", "/remoting/files/bar/foo.zip"})
    void shouldAllowIfEnoughDiskSpaceIsAvailable(String path) throws IOException, ServletException {
        request = HttpRequestBuilder.POST(path).withHeader("X-GO-ARTIFACT-SIZE", FileSize.valueOf("100MB").getSize()).build();

        filter.doFilter(request, response, filterChain);

        assertThat(response)
                .isOk();
        verify(filterChain).doFilter(wrap(request), wrap(response));
    }

    @ParameterizedTest
    @ValueSource(strings = {"/files/bar/foo.zip", "/remoting/files/bar/foo.zip"})
    void shouldDisallowIfNotEnoughDiskSpaceIsAvailable(String path) throws IOException, ServletException {
        request = HttpRequestBuilder.POST(path).withHeader("X-GO-ARTIFACT-SIZE", FileSize.valueOf("600MB").getSize()).build();

        filter.doFilter(request, response, filterChain);

        assertThat(response)
                .isEntityTooLarge();

        verify(filterChain, never()).doFilter(request, response);
    }
}

@@ -1033,67 +1033,8 @@
 er;%0A
-import com.thoughtworks.go.server.service.GoConfigService;%0A
 impo
@@ -1080,16 +1080,16 @@
 onment;%0A
+
 import o
@@ -1640,41 +1640,8 @@
 t %7B%0A
-%0A    private File artifactsDir;%0A%0A
     
@@ -1669,34 +1669,29 @@
 etRe
-quest request;%0A    private
+sponse response = new
  Moc
@@ -1710,25 +1710,18 @@
 Response
- response
+()
 ;%0A    pr
@@ -1842,32 +1842,37 @@
 tUp() %7B%0A        
+File 
 artifactsDir = s
@@ -1874,25 +1874,23 @@
 r = 
-spy(new File(%22.%22)
+mock(File.class
 );%0A 
@@ -1991,220 +1991,93 @@
     
-GoConfigService goConfigService = mock(GoConfigService.class);%0A        when(goConfigService.artifactsDir()).thenReturn(artifactsDir);%0A%0A        response = new MockHttpServletResponse();%0A        ArtifactsDirHolder 
+ArtifactsDirHolder artifactsDirHolder = mock(ArtifactsDirHolder.class);%0A        when(
 arti
@@ -2090,23 +2090,20 @@
 irHolder
- = new 
+.get
 Artifact
@@ -2110,77 +2110,35 @@
 sDir
-Holder(null, goConfigService);%0A        artifactsDirHolder.initialize(
+()).thenReturn(artifactsDir
 );%0A 
@@ -2540,32 +2540,55 @@
 ption %7B%0A        
+MockHttpServletRequest 
 request = HttpRe
@@ -3015,32 +3015,55 @@
 ption %7B%0A        
+MockHttpServletRequest 
 request = HttpRe
@@ -3566,24 +3566,24 @@
 ption %7B%0A
-
         
 request 
@@ -3574,16 +3574,39 @@
         
+MockHttpServletRequest 
 request 

Correct `ArtifactSizeEnforcementFilterChainTest` to not rely on private internals of `File`s