Skip to content

Commit

Permalink
Truncate long string before insert into database (#267)
Browse files Browse the repository at this point in the history
Co-authored-by: gongy <[email protected]>
Co-authored-by: Tim Jacomb <[email protected]>
Fix #264
  • Loading branch information
topikachu authored Dec 1, 2022
1 parent 99e45ac commit 72df1da
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@
@Extension
public class DatabaseTestResultStorage extends JunitTestResultStorage {

static final int MAX_JOB_LENGTH = 255;
static final int MAX_SUITE_LENGTH = 255;
static final int MAX_PACKAGE_LENGTH = 255;
static final int MAX_CLASSNAME_LENGTH = 255;
static final int MAX_TEST_NAME_LENGTH = 500;
static final int MAX_STDOUT_LENGTH = 100000;
static final int MAX_STDERR_LENGTH = 100000;
static final int MAX_STACK_TRACE_LENGTH = 100000;
static final int MAX_ERROR_DETAILS_LENGTH = 100000;
static final int MAX_SKIPPED_LENGTH = 1000;

private transient ConnectionSupplier connectionSupplier;

private boolean skipCleanupRunsOnDeletion;
Expand Down Expand Up @@ -109,36 +120,37 @@ private static class RemotePublisherImpl implements RemotePublisher {
int count = 0;
for (SuiteResult suiteResult : result.getSuites()) {
for (CaseResult caseResult : suiteResult.getCases()) {
statement.setString(1, job);
statement.setString(1, StringUtils.truncate(job, MAX_JOB_LENGTH));
statement.setInt(2, build);
statement.setString(3, suiteResult.getName());
statement.setString(4, caseResult.getPackageName());
statement.setString(5, caseResult.getClassName());
statement.setString(6, caseResult.getName());
statement.setString(3, StringUtils.truncate(suiteResult.getName(), MAX_SUITE_LENGTH));
statement.setString(4, StringUtils.truncate(caseResult.getPackageName(), MAX_PACKAGE_LENGTH));
statement.setString(5, StringUtils.truncate(caseResult.getClassName(), MAX_CLASSNAME_LENGTH));
statement.setString(6, StringUtils.truncate(caseResult.getName(), MAX_TEST_NAME_LENGTH));
String errorDetails = caseResult.getErrorDetails();
if (errorDetails != null) {
errorDetails = StringUtils.truncate(errorDetails, MAX_ERROR_DETAILS_LENGTH);
statement.setString(7, errorDetails);
} else {
statement.setNull(7, Types.VARCHAR);
}
if (caseResult.isSkipped()) {
statement.setString(8, Util.fixNull(caseResult.getSkippedMessage()));
statement.setString(8, StringUtils.truncate(Util.fixNull(caseResult.getSkippedMessage()), MAX_SKIPPED_LENGTH));
} else {
statement.setNull(8, Types.VARCHAR);
}
statement.setFloat(9, caseResult.getDuration());
if (StringUtils.isNotEmpty(caseResult.getStdout())) {
statement.setString(10, caseResult.getStdout());
statement.setString(10, StringUtils.truncate(caseResult.getStdout(), MAX_STDOUT_LENGTH));
} else {
statement.setNull(10, Types.VARCHAR);
}
if (StringUtils.isNotEmpty(caseResult.getStderr())) {
statement.setString(11, caseResult.getStderr());
statement.setString(11, StringUtils.truncate(caseResult.getStderr(), MAX_STDERR_LENGTH));
} else {
statement.setNull(11, Types.VARCHAR);
}
if (StringUtils.isNotEmpty(caseResult.getErrorStackTrace())) {
statement.setString(12, caseResult.getErrorStackTrace());
statement.setString(12, StringUtils.truncate(caseResult.getErrorStackTrace(), MAX_STACK_TRACE_LENGTH));
} else {
statement.setNull(12, Types.VARCHAR);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.collect.ImmutableSet;
import hudson.model.Label;
import hudson.model.Result;
import hudson.slaves.DumbSlave;
import hudson.tasks.junit.CaseResult;
import hudson.tasks.junit.PackageResult;
import hudson.tasks.junit.SuiteResult;
Expand All @@ -11,11 +12,11 @@
import hudson.tasks.junit.TestResultSummary;
import hudson.tasks.junit.TrendTestResultSummary;
import hudson.util.Secret;
import io.jenkins.plugins.junit.storage.JunitTestResultStorage;
import io.jenkins.plugins.junit.storage.JunitTestResultStorageConfiguration;
import io.jenkins.plugins.junit.storage.TestResultImpl;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
Expand Down Expand Up @@ -44,6 +45,8 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import static io.jenkins.plugins.junit.storage.database.DatabaseTestResultStorage.MAX_ERROR_DETAILS_LENGTH;
import static io.jenkins.plugins.junit.storage.database.DatabaseTestResultStorage.MAX_SUITE_LENGTH;
import static java.util.Objects.requireNonNull;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
Expand Down Expand Up @@ -326,6 +329,61 @@ public void testResultCleanup_skipped_if_disabled() throws Exception {
}


@Test
public void testResult_long_string() throws Exception {
try (PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>(TEST_IMAGE)) {
setupPlugin(postgres);

DatabaseTestResultStorage storage = new DatabaseTestResultStorage();
JunitTestResultStorageConfiguration.get().setStorage(storage);


WorkflowJob p = r.createProject(WorkflowJob.class, "p");

p.setDefinition(new CpsFlowDefinition(
"node('remote') {\n" +
" def s = junit 'x.xml'\n" +
" echo(/summary: fail=$s.failCount skip=$s.skipCount pass=$s.passCount total=$s.totalCount/)\n" +
" writeFile file: 'x.xml', text: '''<testsuite name='supersweet'>" +
"<testcase classname='another.Klazz' name='test1'><error message='another failure'/></testcase>" +
"</testsuite>'''\n" +
" s = junit 'x.xml'\n" +
" echo(/next summary: fail=$s.failCount skip=$s.skipCount pass=$s.passCount total=$s.totalCount/)\n" +
"}", true));

//Because writeFile can't handle long string
//We use file copy to prepare the test result
DumbSlave agent = r.createOnlineSlave(Label.get("remote"));
URI longStringFileUri = DatabaseTestResultStorageTest.class.getResource("long-string.xml").toURI();
agent.getWorkspaceFor(p).child("x.xml").copyFrom(longStringFileUri.toURL());
WorkflowRun b = p.scheduleBuild2(0).get();
r.assertBuildStatus(Result.UNSTABLE, b);


// 1 sets of test results
try (Connection connection = requireNonNull(GlobalDatabaseConfiguration.get().getDatabase()).getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT count(*) FROM caseResults");
ResultSet result = statement.executeQuery()) {
result.next();
int anInt = result.getInt(1);
assertThat(anInt, is(4));
}

try (Connection connection = requireNonNull(GlobalDatabaseConfiguration.get().getDatabase()).getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT job, build, suite, package, className, testName, errorDetails, skipped, duration, stdout, stderr, stacktrace FROM caseResults where testName='test1'");
ResultSet result = statement.executeQuery()) {
result.next();
String suiteNameInDatabase = result.getString("suite");
assertThat(suiteNameInDatabase.length(), is(MAX_SUITE_LENGTH));
String errorDetailsInDatabase = result.getString("errorDetails");
assertThat(errorDetailsInDatabase.length(), is(MAX_ERROR_DETAILS_LENGTH));
}


}
}


private void setupPlugin(PostgreSQLContainer<?> postgres) throws SQLException {
// comment this out if you hit the below test containers issue
postgres.start();
Expand Down

Large diffs are not rendered by default.

0 comments on commit 72df1da

Please sign in to comment.