TW-57802 Remove unnecessary ""'git config http.sslCAInfo' command failed" warnings...
[teamcity/git-plugin.git] / git-tests / src / jetbrains / buildServer / buildTriggers / vcs / git / tests / SSLInvestigatorTest.java
1 /*
2  * Copyright 2000-2018 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package jetbrains.buildServer.buildTriggers.vcs.git.tests;
18
19 import com.sun.net.httpserver.HttpsServer;
20 import jetbrains.buildServer.TempFiles;
21 import jetbrains.buildServer.buildTriggers.vcs.git.agent.*;
22 import jetbrains.buildServer.buildTriggers.vcs.git.agent.command.GetConfigCommand;
23 import jetbrains.buildServer.buildTriggers.vcs.git.agent.command.SetConfigCommand;
24 import jetbrains.buildServer.buildTriggers.vcs.git.agent.ssl.SSLInvestigator;
25 import jetbrains.buildServer.serverSide.BasePropertiesModel;
26 import jetbrains.buildServer.serverSide.TeamCityProperties;
27 import org.eclipse.jgit.transport.URIish;
28 import org.jmock.Expectations;
29 import org.jmock.Mockery;
30 import org.jmock.lib.legacy.ClassImposteriser;
31 import org.testng.annotations.*;
32
33 import java.io.File;
34 import java.net.URL;
35 import java.util.Collections;
36 import java.util.Optional;
37
38 import static org.testng.Assert.*;
39
40 /**
41  * Unit tests for {@link SSLInvestigator}.
42  *
43  * @author Mikhail Khorkov
44  * @since 2018.1.2
45  */
46 @Test
47 public class SSLInvestigatorTest {
48
49   private TempFiles myTempFiles = new TempFiles();
50   private File myHomeDirectory;
51   private File myTempDirectory;
52   private Mockery myMockery;
53   private LoggingGitMetaFactory myLoggingFactory;
54
55   private HttpsServer myServer;
56   private SSLTestUtil mySSLTestUtil;
57   private int myServerPort;
58
59   private enum Plot {FEATURE_OFF, GOOD_CERT, BAD_CERT, NO_CERT}
60
61   private enum Result {ONLY_GET, ONLY_SET, GET_AND_SET, GET_AND_UNSET}
62
63   @BeforeClass
64   public void init() throws Exception {
65     mySSLTestUtil = new SSLTestUtil();
66     myServer = mySSLTestUtil.getHttpsServer();
67     myServerPort = mySSLTestUtil.getServerPort();
68     myServer.start();
69   }
70
71   @AfterClass
72   public void down() {
73     myServer.stop(0);
74   }
75
76   @BeforeMethod
77   public void setUp() throws Exception {
78     myHomeDirectory = myTempFiles.createTempDir();
79     myTempDirectory = myTempFiles.createTempDir();
80
81     new TeamCityProperties() {{
82       setModel(new BasePropertiesModel() {
83       });
84     }};
85
86     myMockery = new Mockery() {{
87       setImposteriser(ClassImposteriser.INSTANCE);
88     }};
89     myLoggingFactory = new LoggingGitMetaFactory();
90   }
91
92   @AfterMethod
93   public void tearDown() {
94     myTempFiles.cleanup();
95   }
96
97   @DataProvider(name = "invariants")
98   public static Object[][] invariants() {
99     return new Object[][] {
100       /* plot of  prerequisites | custom flag is set already | expected result */
101       new Object[]{Plot.FEATURE_OFF, false, Result.ONLY_GET},
102       new Object[]{Plot.FEATURE_OFF, true, Result.GET_AND_UNSET},
103
104       new Object[]{Plot.BAD_CERT, false, Result.ONLY_GET},
105       new Object[]{Plot.BAD_CERT, true, Result.GET_AND_UNSET},
106
107       new Object[]{Plot.NO_CERT, false, Result.ONLY_GET},
108       new Object[]{Plot.NO_CERT, true, Result.GET_AND_UNSET},
109
110       new Object[]{Plot.GOOD_CERT, false, Result.ONLY_SET},
111       new Object[]{Plot.GOOD_CERT, true, Result.ONLY_SET},
112     };
113   }
114
115   @Test(dataProvider = "invariants")
116   public void allTest(Plot plot, boolean alreadySet, Result result) throws Exception {
117     switch (plot) {
118       case FEATURE_OFF: {
119         System.setProperty("teamcity.ssl.useCustomTrustStore.git", "false");
120         break;
121       }
122       case NO_CERT: {
123         System.setProperty("teamcity.ssl.useCustomTrustStore.git", "true");
124         break;
125       }
126       case BAD_CERT: {
127         System.setProperty("teamcity.ssl.useCustomTrustStore.git", "true");
128         myTempFiles.registerAsTempFile(mySSLTestUtil.writeAnotherCert(myHomeDirectory));
129         break;
130       }
131       case GOOD_CERT: {
132         System.setProperty("teamcity.ssl.useCustomTrustStore.git", "true");
133         myTempFiles.registerAsTempFile(mySSLTestUtil.writeServerCert(myHomeDirectory));
134         break;
135       }
136     }
137
138     final String alreadyInProperties = alreadySet ? "something" : "";
139     myLoggingFactory.addCallback(GetConfigCommand.class.getName() + ".call",
140                                  (method, args) -> Optional.of(alreadyInProperties));
141     myLoggingFactory.addCallback(SetConfigCommand.class.getName() + ".call",
142                                  (method, args) -> Optional.empty());
143
144     final SSLInvestigator instance = createInstance();
145
146     instance.setCertificateOptions(createFactory().create(myTempDirectory));
147
148     switch (result) {
149       case ONLY_GET: {
150         assertEquals(myLoggingFactory.getNumberOfCalls(GetConfigCommand.class), 1);
151         assertEquals(myLoggingFactory.getNumberOfCalls(SetConfigCommand.class), 0);
152         break;
153       }
154       case ONLY_SET: {
155         assertEquals(myLoggingFactory.getNumberOfCalls(GetConfigCommand.class), 0);
156         assertEquals(myLoggingFactory.getNumberOfCalls(SetConfigCommand.class), 1);
157         assertFalse(myLoggingFactory.getInvokedMethods(SetConfigCommand.class).contains("unSet"));
158         break;
159       }
160       case GET_AND_SET: {
161         assertEquals(myLoggingFactory.getNumberOfCalls(GetConfigCommand.class), 1);
162         assertEquals(myLoggingFactory.getNumberOfCalls(SetConfigCommand.class), 1);
163         assertFalse(myLoggingFactory.getInvokedMethods(SetConfigCommand.class).contains("unSet"));
164         break;
165       }
166       case GET_AND_UNSET: {
167         assertEquals(myLoggingFactory.getNumberOfCalls(GetConfigCommand.class), 1);
168         assertEquals(myLoggingFactory.getNumberOfCalls(SetConfigCommand.class), 1);
169         assertTrue(myLoggingFactory.getInvokedMethods(SetConfigCommand.class).contains("unSet"));
170         break;
171       }
172     }
173   }
174
175   private SSLInvestigator createInstance() throws Exception {
176     return new SSLInvestigator(new URIish(new URL("https://localhost:" + myServerPort)), myTempDirectory.getPath(), myHomeDirectory.getPath());
177   }
178
179   private GitFactory createFactory() throws Exception {
180     final GitAgentSSHService ssh = myMockery.mock(GitAgentSSHService.class);
181     final AgentPluginConfig pluginConfig = myMockery.mock(AgentPluginConfig.class);
182     final Context context = myMockery.mock(Context.class);
183     myMockery.checking(new Expectations() {{
184       atLeast(1).of(pluginConfig).getPathToGit();
185       will(returnValue("git"));
186       atLeast(1).of(pluginConfig).getGitVersion();
187       will(returnValue(GitVersion.MIN));
188       atLeast(1).of(pluginConfig).isDeleteTempFiles();
189       will(returnValue(false));
190       atLeast(1).of(pluginConfig).getGitExec();
191       will(returnValue(myMockery.mock(GitExec.class)));
192     }});
193     final GitProgressLogger logger = myMockery.mock(GitProgressLogger.class);
194     return myLoggingFactory.createFactory(ssh, pluginConfig, logger, myTempFiles.createTempDir(), Collections.emptyMap(), context);
195   }
196 }