// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.uber.jenkins.phabricator;
import com.uber.jenkins.phabricator.coverage.CoberturaXMLParser;
import com.uber.jenkins.phabricator.lint.LintResult;
import com.uber.jenkins.phabricator.lint.LintResults;
import com.uber.jenkins.phabricator.uberalls.UberallsClient;
import com.uber.jenkins.phabricator.unit.JUnitTestProvider;
import com.uber.jenkins.phabricator.utils.TestUtils;
import hudson.model.FreeStyleBuild;
import hudson.model.Result;
import net.sf.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
public class PhabricatorNotifierTest extends BuildIntegrationTest {
private PhabricatorNotifier notifier;
@Before
public void setUp() throws IOException {
p = createProject();
notifier = new PhabricatorNotifier(
false,
true,
false,
0.0,
true,
".phabricator-comment",
"1001",
false,
true,
true,
".phabricator-lint",
"10000"
);
}
@Test
public void testGetters() {
assertFalse(notifier.isCommentOnSuccess());
assertTrue(notifier.isUberallsEnabled());
assertFalse(notifier.isCoverageCheck());
assertEquals(0.0, notifier.getCoverageThreshold(), 0);
assertTrue(notifier.isPreserveFormatting());
assertEquals(".phabricator-comment", notifier.getCommentFile());
assertEquals("1001", notifier.getCommentSize());
assertFalse(notifier.isCommentWithConsoleLinkOnFailure());
assertTrue(notifier.isProcessLint());
assertEquals(".phabricator-lint", notifier.getLintFile());
assertEquals("10000", notifier.getLintFileSize());
}
@Test
public void testRoundTripConfiguration() throws Exception {
addBuildStep();
j.submit(j.createWebClient().getPage(p, "configure").getFormByName("config"));
PhabricatorNotifier after = p.getPublishersList().get(PhabricatorNotifier.class);
j.assertEqualBeans(notifier, after,
"commentOnSuccess,uberallsEnabled,commentWithConsoleLinkOnFailure,commentFile,commentSize");
}
@Test
public void testNoParametersBuild() throws Exception {
addBuildStep();
FreeStyleBuild build = p.scheduleBuild2(0).get();
Result result = build.getResult();
assertSuccessfulBuild(result);
}
@Test
public void testNoCredentials() throws Exception {
addBuildStep();
TestUtils.setDefaultBuildEnvironment(j);
FreeStyleBuild build = p.scheduleBuild2(0).get();
assertFailureWithMessage("No credentials configured for conduit", build);
}
@Test
public void testWithCredentialsIgnoresMissingConduit() throws Exception {
FreeStyleBuild build = buildWithConduit(null, null, null);
assertEquals(Result.SUCCESS, build.getResult());
assertLogContains("Unable to fetch differential", build);
}
@Test
public void testUnableToPostToHarbormaster() throws Exception {
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, null);
assertFailureWithMessage("Unable to post to Harbormaster", build);
}
@Test
public void testPostToHarbormaster() throws Exception {
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
}
@Test
public void testPostToHarbormasterValidLint() throws Exception {
JSONObject json = new JSONObject();
LintResults result = new LintResults();
result.add(new LintResult("test", "testcode", "error", "to/path", 10, 3, "test description"));
json.element("lint", result);
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, json);
assertEquals(Result.SUCCESS, build.getResult());
}
@Test
public void testPostCoverage() throws Exception {
TestUtils.addCopyBuildStep(p, TestUtils.COBERTURA_XML, CoberturaXMLParser.class, "go-torch-coverage.xml");
p.getPublishersList().add(TestUtils.getDefaultCoberturaPublisher());
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
assertLogContains("Publishing coverage data to Harbormaster for 3 files", build);
}
@Test
public void testFailBuildOnDecreasedCoverage() throws Exception {
TestUtils.addCopyBuildStep(p, TestUtils.COBERTURA_XML, CoberturaXMLParser.class, "go-torch-coverage2.xml");
UberallsClient uberalls = TestUtils.getDefaultUberallsClient();
notifier = getDecreasedLineCoverageNotifier(0.0);
when(uberalls.getCoverage(any(String.class))).thenReturn("{\n" +
" \"sha\": \"deadbeef\",\n" +
" \"lineCoverage\": 100,\n" +
" \"filesCoverage\": 100,\n" +
" \"packageCoverage\": 100,\n" +
" \"classesCoverage\": 100,\n" +
" \"methodCoverage\": 100,\n" +
" \"conditionalCoverage\": 100\n" +
"}");
notifier.getDescriptor().setUberallsURL("http://uber.alls");
notifier.setUberallsClient(uberalls);
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.FAILURE, build.getResult());
assertLogContains("Sending build result to Harbormaster with PHID PHID-not-real, success: false", build);
}
@Test
public void testPassBuildOnDecreasedCoverageGreaterThanMaxPercent() throws Exception {
TestUtils.addCopyBuildStep(p, TestUtils.COBERTURA_XML, CoberturaXMLParser.class, "go-torch-coverage2.xml");
UberallsClient uberalls = TestUtils.getDefaultUberallsClient();
notifier = getDecreasedLineCoverageNotifier(-5.0);
when(uberalls.getCoverage(any(String.class))).thenReturn("{\n" +
" \"sha\": \"deadbeef\",\n" +
" \"lineCoverage\": 100,\n" +
" \"filesCoverage\": 100,\n" +
" \"packageCoverage\": 100,\n" +
" \"classesCoverage\": 100,\n" +
" \"methodCoverage\": 100,\n" +
" \"conditionalCoverage\": 100\n" +
"}");
notifier.getDescriptor().setUberallsURL("http://uber.alls");
notifier.setUberallsClient(uberalls);
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
}
@Test
public void testPassBuildOnSameCoverage() throws Exception {
TestUtils.addCopyBuildStep(p, TestUtils.COBERTURA_XML, CoberturaXMLParser.class, "go-torch-coverage2.xml");
UberallsClient uberalls = TestUtils.getDefaultUberallsClient();
notifier = getDecreasedLineCoverageNotifier(0.0);
when(uberalls.getCoverage(any(String.class))).thenReturn("{\n" +
" \"sha\": \"deadbeef\",\n" +
" \"lineCoverage\": 0.0,\n" +
" \"packageCoverage\": 0,\n" +
" \"classesCoverage\": 0,\n" +
" \"methodCoverage\": 0,\n" +
" \"conditionalCoverage\": 0\n" +
"}");
notifier.setUberallsClient(uberalls);
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
}
@Test
public void testPassBuildOnPositiveMaximumCoverageDecrease() throws Exception {
TestUtils.addCopyBuildStep(p, TestUtils.COBERTURA_XML, CoberturaXMLParser.class, "go-torch-coverage2.xml");
UberallsClient uberalls = TestUtils.getDefaultUberallsClient();
notifier = getDecreasedLineCoverageNotifier(0.01);
when(uberalls.getCoverage(any(String.class))).thenReturn("{\n" +
" \"sha\": \"deadbeef\",\n" +
" \"lineCoverage\": 95.2391,\n" +
" \"filesCoverage\": 0,\n" +
" \"packageCoverage\": 0,\n" +
" \"classesCoverage\": 0,\n" +
" \"methodCoverage\": 0,\n" +
" \"conditionalCoverage\": 0\n" +
"}");
notifier.setUberallsClient(uberalls);
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
}
@Test
public void testPostCoverageWithoutPublisher() throws Exception {
TestUtils.addCopyBuildStep(p, "src/coverage/" + TestUtils.COBERTURA_XML, CoberturaXMLParser.class, "go-torch-coverage.xml");
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
assertLogContains("Publishing coverage data to Harbormaster for 3 files", build);
}
@Test
public void testPostUnit() throws Exception {
TestUtils.addCopyBuildStep(p, TestUtils.JUNIT_XML, JUnitTestProvider.class, "go-torch-junit.xml");
p.getPublishersList().add(TestUtils.getDefaultXUnitPublisher());
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
assertLogContains("Publishing unit results to Harbormaster for 35 tests", build);
}
@Test
public void testPostUnitWithFailure() throws Exception {
TestUtils.addCopyBuildStep(p, TestUtils.JUNIT_XML, JUnitTestProvider.class, "go-torch-junit-fail.xml");
p.getPublishersList().add(TestUtils.getDefaultXUnitPublisher());
FreeStyleBuild build = buildWithConduit(getFetchDiffResponse(), null, new JSONObject());
assertEquals(Result.UNSTABLE, build.getResult());
assertLogContains("Publishing unit results to Harbormaster for 8 tests", build);
FakeConduit conduitTestClient = getConduitClient();
// There are two requests, first it fetches the diff info, secondly it posts the unit result to harbormaster
assertEquals(2, conduitTestClient.getRequestBodies().size());
String actualUnitResultWithFailureRequestBody = conduitTestClient.getRequestBodies().get(1);
assertConduitRequest(getUnitResultWithFailureRequest(), actualUnitResultWithFailureRequestBody);
}
@Test
public void testPostCoverageUberallsDisabled() throws Exception {
notifier = new PhabricatorNotifier(
false,
false,
false,
0.0,
true,
".phabricator-comment",
"1000",
false,
true,
true,
".phabricator-lint",
"10000"
);
testPostCoverage();
}
@Test
public void testNonDifferentialWithPHID() throws Exception {
FreeStyleBuild build = buildWithCommit(new JSONObject());
assertEquals(Result.SUCCESS, build.getResult());
assertLogContains("Sending diffusion result", build);
}
@Test
public void testDescriptor() {
PhabricatorNotifierDescriptor descriptor = notifier.getDescriptor();
assertNull(descriptor.getCredentialsID());
assertNull(descriptor.getUberallsURL());
descriptor.setCredentialsID("not-a-real-uuid");
descriptor.setUberallsURL("http://uber.alls");
}
@Override
protected void addBuildStep() {
p.getPublishersList().add(notifier);
}
protected PhabricatorNotifier getDecreasedLineCoverageNotifier(double threshold) {
return new PhabricatorNotifier(
false,
true,
true,
threshold,
true,
".phabricator-comment",
"1001",
false,
true,
true,
".phabricator-lint",
"10000"
);
}
}