/* * Copyright 2016-present Facebook, 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.facebook.buck.doctor; import static org.hamcrest.junit.MatcherAssume.assumeThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import com.facebook.buck.cli.BuckConfig; import com.facebook.buck.cli.FakeBuckConfig; import com.facebook.buck.doctor.config.DoctorConfig; import com.facebook.buck.doctor.config.DoctorEndpointRequest; import com.facebook.buck.doctor.config.DoctorEndpointResponse; import com.facebook.buck.doctor.config.DoctorSuggestion; import com.facebook.buck.rage.BuildLogEntry; import com.facebook.buck.rage.BuildLogHelper; import com.facebook.buck.rage.DefectSubmitResult; import com.facebook.buck.rage.RageConfig; import com.facebook.buck.rage.UserInput; import com.facebook.buck.rage.UserInputFixture; import com.facebook.buck.testutil.TestConsole; import com.facebook.buck.testutil.integration.HttpdForTests; import com.facebook.buck.testutil.integration.ProjectWorkspace; import com.facebook.buck.testutil.integration.TemporaryPaths; import com.facebook.buck.testutil.integration.TestDataHelper; import com.facebook.buck.util.BuckConstant; import com.facebook.buck.util.ObjectMappers; import com.facebook.buck.util.environment.Platform; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteStreams; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; public class DoctorCommandIntegrationTest { @Rule public TemporaryPaths tempFolder = new TemporaryPaths(); private ProjectWorkspace workspace; private HttpdForTests httpd; private DoctorEndpointResponse doctorResponse; private DefectSubmitResult rageResult; private final AtomicReference<String> requestMethod = new AtomicReference<>(); private final AtomicReference<String> requestPath = new AtomicReference<>(); private final AtomicReference<byte[]> requestBody = new AtomicReference<>(); private static final String LOG_PATH = BuckConstant.getBuckOutputPath() .resolve("log") .resolve("2016-06-21_16h16m24s_buildcommand_ac8bd626-6137-4747-84dd-5d4f215c876c") .resolve(BuckConstant.BUCK_LOG_FILE_NAME) .toString(); @Before public void setUp() throws Exception { workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "report", tempFolder); workspace.setUp(); rageResult = DefectSubmitResult.builder() .setIsRequestSuccessful(true) .setReportSubmitErrorMessage(Optional.empty()) .setReportSubmitMessage("This is a json/string generated by the remote server.") .setRequestProtocol(RageConfig.RageProtocolVersion.JSON) .build(); doctorResponse = DoctorEndpointResponse.of( Optional.empty(), ImmutableList.of( DoctorSuggestion.of( DoctorSuggestion.StepStatus.ERROR, Optional.empty(), "Suggestion no1"), DoctorSuggestion.of( DoctorSuggestion.StepStatus.WARNING, Optional.of("Area"), "Suggestion no2"))); httpd = new HttpdForTests(); httpd.addHandler( createHttpdHandler( "POST", "{\"buildId\":\"ac8bd626-6137-4747-84dd-5d4f215c876c\",\"logDirPath\":\"" + LOG_PATH + "\",\"machineReadableLog\"")); httpd.start(); } @After public void cleanUp() throws Exception { httpd.close(); } @Test public void testEndpointUrl() throws Exception { DoctorReportHelper helper = createDoctorHelper( (new UserInputFixture("0")).getUserInput(), DoctorConfig.of(FakeBuckConfig.builder().build())); BuildLogHelper buildLogHelper = new BuildLogHelper(workspace.asCell().getFilesystem()); Optional<BuildLogEntry> entry = helper.promptForBuild(new ArrayList<>(buildLogHelper.getBuildLogs())); DoctorEndpointRequest request = helper.generateEndpointRequest(entry.get(), rageResult); DoctorEndpointResponse response = helper.uploadRequest(request); assertEquals( "Please define URL", response.getErrorMessage().get(), "Doctor endpoint URL is not set. Please set [doctor] endpoint_url on your .buckconfig"); } @Test public void testPromptWithoutRageReport() throws Exception { assumeThat(Platform.detect(), Matchers.not(Matchers.is(Platform.WINDOWS))); DoctorReportHelper helper = createDoctorHelper((new UserInputFixture("0")).getUserInput(), createDoctorConfig(httpd)); BuildLogHelper buildLogHelper = new BuildLogHelper(workspace.asCell().getFilesystem()); Optional<BuildLogEntry> entry = helper.promptForBuild(new ArrayList<>(buildLogHelper.getBuildLogs())); DoctorEndpointRequest request = helper.generateEndpointRequest(entry.get(), rageResult); DoctorEndpointResponse response = helper.uploadRequest(request); helper.presentResponse(response); assertEquals(response, doctorResponse); assertEquals( "\n:: Suggestions\n- [Error] Suggestion no1\n- [Warning][Area] Suggestion no2\n\n", ((TestConsole) helper.getConsole()).getTextWrittenToStdOut()); } private AbstractHandler createHttpdHandler( final String expectedMethod, final String expectedBody) { return new AbstractHandler() { @Override public void handle( String s, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { httpResponse.setStatus(200); request.setHandled(true); if (request.getUri().getPath().equals("/status.php")) { return; } httpResponse.setContentType("application/json"); httpResponse.setCharacterEncoding("utf-8"); requestPath.set(request.getUri().getPath()); requestMethod.set(request.getMethod()); requestBody.set(ByteStreams.toByteArray(httpRequest.getInputStream())); assertTrue(requestMethod.get().equalsIgnoreCase(expectedMethod)); assertThat( "Request should contain the uuid.", new String(requestBody.get(), Charsets.UTF_8), Matchers.containsString(expectedBody)); try (DataOutputStream out = new DataOutputStream(httpResponse.getOutputStream())) { ObjectMappers.WRITER.writeValue(out, doctorResponse); } } }; } private static DoctorConfig createDoctorConfig(HttpdForTests httpd) { String uri = "http://localhost:" + httpd.getRootUri().getPort(); BuckConfig buckConfig = FakeBuckConfig.builder() .setSections( ImmutableMap.of( DoctorConfig.DOCTOR_SECTION, ImmutableMap.of(DoctorConfig.URL_FIELD, uri))) .build(); return DoctorConfig.of(buckConfig); } private DoctorReportHelper createDoctorHelper(UserInput input, DoctorConfig doctorConfig) throws Exception { return new DoctorReportHelper( workspace.asCell().getFilesystem(), input, new TestConsole(), doctorConfig); } }