mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
28.29.2014 c2bc444bdc7e4ac083bbdf72ce8eb77ff020f662
Misc improvements to replication Session error reporting.


replication*.properties:
Added exception stacktrace to NOTICE_READER_EXCEPTION_53.

ServerReader.java:
In run(), logged the stacktrace when calling logError(). Removed redundant call to logException() which logged to debug logger.


Session.java:
Extracted method read().


StaticUtils.java:
In stackTraceToSingleLineString(), when this is not a debug build, added the exception type at the start of the message.

StaticUtilsTest.java: ADDED
1 files added
11 files modified
194 ■■■■■ changed files
opendj3-server-dev/src/messages/messages/replication.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication_de.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication_es.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication_fr.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication_ja.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication_ko.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication_zh_CN.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication_zh_TW.properties 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/replication/protocol/Session.java 67 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/replication/server/ServerReader.java 4 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/util/StaticUtils.java 16 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/util/StaticUtilsTest.java 91 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/messages/messages/replication.properties
@@ -110,7 +110,7 @@
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=The hostname %s could not be resolved \
 as an IP address
NOTICE_READER_NULL_MSG_52=Received a Null Msg from %s
NOTICE_READER_EXCEPTION_53=Exception when reading messages from %s
NOTICE_READER_EXCEPTION_53=Exception when reading messages from %s: %s
SEVERE_ERR_DUPLICATE_SERVER_ID_54=In Replication server %s: servers %s and %s \
have the same ServerId : %d
SEVERE_ERR_DUPLICATE_REPLICATION_SERVER_ID_55=In Replication server %s: \
opendj3-server-dev/src/messages/messages/replication_de.properties
@@ -82,7 +82,7 @@
SEVERE_ERR_INVALID_PROVIDER_50=Die Anbieterklasse erlaubt den angeforderten Vorgang nicht
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=Der Hostname %s konnte nicht als eine IP-Adresse aufgel\u00f6st werden
NOTICE_READER_NULL_MSG_52=Nullnachricht von %s empfangen
NOTICE_READER_EXCEPTION_53=Ausnahmefehler beim Lesen von Nachrichten von %s
NOTICE_READER_EXCEPTION_53=Ausnahmefehler beim Lesen von Nachrichten von %s: %s
SEVERE_ERR_DUPLICATE_SERVER_ID_54=In Replikationsserver %s: besitzen Server %s und %s dieselbe Server-ID : %d
SEVERE_ERR_DUPLICATE_REPLICATION_SERVER_ID_55=In Replikationsserver %s: besitzen Replikationsserver %s und %s dieselbe Server-ID : %d
SEVERE_ERR_BAD_HISTORICAL_56=Eintrag %s hat einige unbekannte historische Informatinoen enthalten. Dadurch k\u00f6nnen Inkonsistenzen f\u00fcr diesen Eintrag auftreten
opendj3-server-dev/src/messages/messages/replication_es.properties
@@ -82,7 +82,7 @@
SEVERE_ERR_INVALID_PROVIDER_50=La clase de proveedor no permite la operaci\u00f3n solicitada
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=No pudo resolverse el nombre de host %s como una direcci\u00f3n IP
NOTICE_READER_NULL_MSG_52=Se recibi\u00f3 un mensaje nulo de %s
NOTICE_READER_EXCEPTION_53=Excepci\u00f3n al leer mensajes de %s
NOTICE_READER_EXCEPTION_53=Excepci\u00f3n al leer mensajes de %s: %s
SEVERE_ERR_DUPLICATE_SERVER_ID_54=En el Servidor de repetici\u00f3n %s: los servidores %s y %s tienen el mismo Id. (ServerId): %d
SEVERE_ERR_DUPLICATE_REPLICATION_SERVER_ID_55=En el Servidor de repetici\u00f3n %s: los servidores de repetici\u00f3n %s y %s tienen el mismo Id. (ServerId): %d
SEVERE_ERR_BAD_HISTORICAL_56=La entrada %s conten\u00eda informaci\u00f3n hist\u00f3rica desconocida. Es posible que esto genere incoherencias con respecto a esta entrada
opendj3-server-dev/src/messages/messages/replication_fr.properties
@@ -82,7 +82,7 @@
SEVERE_ERR_INVALID_PROVIDER_50=La classe de fournisseur n'autorise pas l'op\u00e9ration demand\u00e9e
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=Impossible de r\u00e9soudre le nom d'h\u00f4te %s en tant qu'adresse\u00a0IP
NOTICE_READER_NULL_MSG_52=Message null re\u00e7u de %s
NOTICE_READER_EXCEPTION_53=Exception lors de la lecture de messages de %s
NOTICE_READER_EXCEPTION_53=Exception lors de la lecture de messages de %s: %s
SEVERE_ERR_DUPLICATE_SERVER_ID_54=Sur le serveur de r\u00e9plication %s\u00a0: les serveurs %s et %s ont le m\u00eame ID (ServerId)\u00a0: %d
SEVERE_ERR_DUPLICATE_REPLICATION_SERVER_ID_55=Sur le serveur de r\u00e9plication %s\u00a0: les serveurs de r\u00e9plication %s et %s ont le m\u00eame ID (ServerId)\u00a0: %d
SEVERE_ERR_BAD_HISTORICAL_56=L'entr\u00e9e %s contenait des informations historiques inconnues, ce qui peut provoquer des incoh\u00e9rences pour cette entr\u00e9e
opendj3-server-dev/src/messages/messages/replication_ja.properties
@@ -82,7 +82,7 @@
SEVERE_ERR_INVALID_PROVIDER_50=\u8981\u6c42\u3055\u308c\u305f\u64cd\u4f5c\u306f\u30d7\u30ed\u30d0\u30a4\u30c0\u30af\u30e9\u30b9\u3067\u8a31\u53ef\u3055\u308c\u307e\u305b\u3093
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=\u30db\u30b9\u30c8\u540d %s \u3092 IP \u30a2\u30c9\u30ec\u30b9\u3068\u3057\u3066\u89e3\u6c7a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
NOTICE_READER_NULL_MSG_52=%s \u304b\u3089 NULL \u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u53d7\u4fe1\u3057\u307e\u3057\u305f
NOTICE_READER_EXCEPTION_53=%s \u304b\u3089\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8aad\u307f\u53d6\u308a\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f
NOTICE_READER_EXCEPTION_53=%s \u304b\u3089\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8aad\u307f\u53d6\u308a\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: %s
SEVERE_ERR_DUPLICATE_SERVER_ID_54=\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b5\u30fc\u30d0\u30fc %s: \u30b5\u30fc\u30d0\u30fc %s \u3068 %s \u306eServerId \u304c\u540c\u3058\u3067\u3059: %d
SEVERE_ERR_DUPLICATE_REPLICATION_SERVER_ID_55=\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b5\u30fc\u30d0\u30fc %s: \u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b5\u30fc\u30d0\u30fc %s \u3068 %s \u306eServerId \u304c\u540c\u3058\u3067\u3059: %d
SEVERE_ERR_BAD_HISTORICAL_56=\u30a8\u30f3\u30c8\u30ea %s \u306b\u4e0d\u660e\u306a\u5c65\u6b74\u60c5\u5831\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3057\u305f\u3002\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u306b\u77db\u76fe\u304c\u8d77\u304d\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059
opendj3-server-dev/src/messages/messages/replication_ko.properties
@@ -79,7 +79,7 @@
SEVERE_ERR_INVALID_PROVIDER_50=\uc694\uccad\ud55c \uc791\uc5c5\uc744 \uacf5\uae09\uc790 \ud074\ub798\uc2a4\uc5d0\uc11c \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=\ud638\uc2a4\ud2b8 \uc774\ub984 %s\uc744(\ub97c) IP \uc8fc\uc18c\ub85c \ud655\uc778\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.
NOTICE_READER_NULL_MSG_52=%s\uc5d0\uc11c Null \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud588\uc2b5\ub2c8\ub2e4.
NOTICE_READER_EXCEPTION_53=%s\uc5d0\uc11c \uba54\uc2dc\uc9c0\ub97c \uc77d\ub294 \ub3d9\uc548 \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.
NOTICE_READER_EXCEPTION_53=%s\uc5d0\uc11c \uba54\uc2dc\uc9c0\ub97c \uc77d\ub294 \ub3d9\uc548 \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4: %s
SEVERE_ERR_BAD_HISTORICAL_56=%s \ud56d\ubaa9\uc5d0 \uc54c\ub824\uc9c0\uc9c0 \uc54a\uc740 \uc77c\ubd80 \uae30\ub85d \uc815\ubcf4\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. \uc774\ub85c \uc778\ud574 \uc774 \ud56d\ubaa9\uc5d0 \ub300\ud55c \uc77c\ubd80 \ubd88\uc77c\uce58\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.
MILD_ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE_57=\ucda9\ub3cc\uc774 \uac80\uc0c9\ub418\uc5c8\uc9c0\ub9cc \ucda9\ub3cc \uc815\ubcf4\ub97c \ucd94\uac00\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4. \uc791\uc5c5:
MILD_ERR_CANNOT_RENAME_CONFLICT_ENTRY_58=\ucda9\ub3cc\ud558\ub294 \ud56d\ubaa9\uc758 \uc774\ub984\uc744 \ubc14\uafb8\ub294 \ub3d9\uc548 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4:
opendj3-server-dev/src/messages/messages/replication_zh_CN.properties
@@ -82,7 +82,7 @@
SEVERE_ERR_INVALID_PROVIDER_50=\u63d0\u4f9b\u7a0b\u5e8f\u7c7b\u4e0d\u5141\u8bb8\u8bf7\u6c42\u7684\u64cd\u4f5c
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=\u4e3b\u673a\u540d %s \u65e0\u6cd5\u89e3\u6790\u4e3a IP \u5730\u5740
NOTICE_READER_NULL_MSG_52=\u4ece %s \u4e2d\u6536\u5230\u4e86 Null \u6d88\u606f
NOTICE_READER_EXCEPTION_53=\u4ece %s \u4e2d\u8bfb\u53d6\u6d88\u606f\u65f6\u51fa\u73b0\u5f02\u5e38
NOTICE_READER_EXCEPTION_53=\u4ece %s \u4e2d\u8bfb\u53d6\u6d88\u606f\u65f6\u51fa\u73b0\u5f02\u5e38: %s
SEVERE_ERR_DUPLICATE_SERVER_ID_54=\u5728\u590d\u5236\u670d\u52a1\u5668 %s \u4e2d\uff1a\u670d\u52a1\u5668 %s \u548c %s \u5177\u6709\u76f8\u540c\u7684\u670d\u52a1\u5668 ID: %d
SEVERE_ERR_DUPLICATE_REPLICATION_SERVER_ID_55=\u5728\u590d\u5236\u670d\u52a1\u5668 %s \u4e2d\uff1a\u590d\u5236\u670d\u52a1\u5668 %s \u548c %s \u5177\u6709\u76f8\u540c\u7684\u670d\u52a1\u5668 ID: %d
SEVERE_ERR_BAD_HISTORICAL_56=\u6761\u76ee %s \u5305\u542b\u67d0\u4e9b\u672a\u77e5\u7684\u5386\u53f2\u4fe1\u606f\uff0c\u53ef\u80fd\u4f1a\u9020\u6210\u672c\u6761\u76ee\u7684\u4e0d\u4e00\u81f4\u6027
opendj3-server-dev/src/messages/messages/replication_zh_TW.properties
@@ -79,7 +79,7 @@
SEVERE_ERR_INVALID_PROVIDER_50=\u63d0\u4f9b\u8005\u985e\u5225\u4e0d\u5141\u8a31\u8acb\u6c42\u7684\u4f5c\u696d
SEVERE_ERR_COULD_NOT_SOLVE_HOSTNAME_51=\u4e3b\u6a5f\u540d\u7a31 %s \u7121\u6cd5\u89e3\u6790\u70ba IP \u4f4d\u5740
NOTICE_READER_NULL_MSG_52=\u5f9e %s \u63a5\u6536\u5230\u7a7a\u8a0a\u606f
NOTICE_READER_EXCEPTION_53=\u8b80\u53d6\u4f86\u81ea %s \u7684\u8a0a\u606f\u6642\u767c\u751f\u7570\u5e38
NOTICE_READER_EXCEPTION_53=\u8b80\u53d6\u4f86\u81ea %s \u7684\u8a0a\u606f\u6642\u767c\u751f\u7570\u5e38: %s
SEVERE_ERR_BAD_HISTORICAL_56=\u9805\u76ee %s \u5305\u542b\u67d0\u4e9b\u4e0d\u660e\u6b77\u7a0b\u8cc7\u8a0a\uff0c\u9019\u53ef\u80fd\u6703\u5c0e\u81f4\u6b64\u9805\u76ee\u51fa\u73fe\u4e0d\u4e00\u81f4\u7684\u60c5\u6cc1
MILD_ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE_57=\u5075\u6e2c\u5230\u885d\u7a81\uff0c\u4f46\u7121\u6cd5\u589e\u52a0\u885d\u7a81\u8cc7\u8a0a\u3002\u4f5c\u696d:
MILD_ERR_CANNOT_RENAME_CONFLICT_ENTRY_58=\u5617\u8a66\u91cd\u65b0\u547d\u540d\u885d\u7a81\u9805\u76ee\u6642\u767c\u751f\u932f\u8aa4:
opendj3-server-dev/src/server/org/opends/server/replication/protocol/Session.java
@@ -26,16 +26,14 @@
 */
package org.opends.server.replication.protocol;
import static org.opends.server.util.StaticUtils.*;
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -47,8 +45,6 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.opends.server.util.StaticUtils;
/**
 * This class defines a replication session using TLS.
 */
@@ -82,7 +78,7 @@
   */
  private final Object stateLock = new Object();
  private volatile boolean closeInitiated = false;
  private Throwable sessionError = null;
  private Throwable sessionError;
  /**
   * Publish guarded by publishLock: use a full lock here so that we can
@@ -204,9 +200,8 @@
    }
    // V4 protocol introduces a StopMsg to properly end communications.
    if (localSessionError == null)
    {
      if (protocolVersion >= ProtocolVersion.REPLICATION_PROTOCOL_V4)
    if (localSessionError == null
        && protocolVersion >= ProtocolVersion.REPLICATION_PROTOCOL_V4)
      {
        try
        {
@@ -217,7 +212,6 @@
          // Ignore errors on close.
        }
      }
    }
    StaticUtils.close(plainSocket, secureSocket);
  }
@@ -407,50 +401,20 @@
  {
    try
    {
      // Read the first 8 bytes containing the packet length.
      int length = 0;
      /*
       * Let's start the stop-watch before waiting on read for the heartbeat
       * check to be operational.
       */
      lastReceiveTime = System.currentTimeMillis();
      while (length < 8)
      {
        final int read = input.read(rcvLengthBuf, length, 8 - length);
        if (read == -1)
        {
          lastReceiveTime = 0;
          throw new IOException("no more data");
        }
        else
        {
          length += read;
        }
      }
      final int totalLength = Integer.parseInt(new String(
          rcvLengthBuf), 16);
      // Read the first 8 bytes containing the packet length.
      read(rcvLengthBuf);
      final int totalLength = Integer.parseInt(new String(rcvLengthBuf), 16);
      try
      {
        length = 0;
        final byte[] buffer = new byte[totalLength];
        while (length < totalLength)
        {
          final int read = input.read(buffer, length, totalLength
              - length);
          if (read == -1)
          {
            lastReceiveTime = 0;
            throw new IOException("no more data");
          }
          else
          {
            length += read;
          }
        }
        read(buffer);
        /*
         * We do not want the heartbeat to close the session when we are
@@ -487,6 +451,21 @@
    }
  }
  private void read(byte[] buffer) throws IOException
  {
    final int totalLength = buffer.length;
    int length = 0;
    while (length < totalLength)
    {
      final int read = input.read(buffer, length, totalLength - length);
      if (read == -1)
      {
        lastReceiveTime = 0;
        throw new IOException("no more data");
      }
      length += read;
    }
  }
  /**
   * This method is called at the establishment of the session and can
opendj3-server-dev/src/server/org/opends/server/replication/server/ServerReader.java
@@ -254,12 +254,12 @@
    }
    catch (Exception e)
    {
      logException(e);
      /*
       * The remote server has sent an unknown message,
       * close the connection.
       */
      errMessage = NOTE_READER_EXCEPTION.get(handler.toString());
      errMessage = NOTE_READER_EXCEPTION.get(
          handler.toString(), stackTraceToSingleLineString(e));
      logError(errMessage);
    }
    finally
opendj3-server-dev/src/server/org/opends/server/util/StaticUtils.java
@@ -1680,19 +1680,11 @@
        t = t.getCause();
      }
      String message = t.getMessage();
      if ((message == null) || (message.length() == 0))
      buffer.append(t.getClass().getSimpleName());
      final String message = t.getMessage();
      if (message != null && message.length() != 0)
      {
        String className = t.getClass().getName();
        try
        {
          className = className.substring(className.lastIndexOf('.') + 1);
        } catch (Exception e) { /* ignored */ }
        buffer.append(className);
      }
      else
      {
        buffer.append(message);
        buffer.append(": ").append(message);
      }
      int i=0;
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/util/StaticUtilsTest.java
New file
@@ -0,0 +1,91 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at legal-notices/CDDLv1_0.txt.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *      Copyright 2014 ForgeRock AS
 */
package org.opends.server.util;
import java.lang.reflect.InvocationTargetException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.*;
@SuppressWarnings("javadoc")
public class StaticUtilsTest extends UtilTestCase
{
  @DataProvider
  public Object[][] stackTraceToSingleLineString()
  {
    final String message = "This is a tremendous error message";
    final String noMessageStackTrace = "Exception (" + getClass().getSimpleName() + ".java:";
    final String messageStackTrace = "Exception: " + message + " (" + getClass().getSimpleName() + ".java:";
    return new Object[][] {
      { null, "" },
      { new Exception(), noMessageStackTrace },
      { new Exception(message), messageStackTrace },
      { new Exception(new Exception()), "Exception: java.lang.Exception (" + getClass().getSimpleName() + ".java:" },
      { new Exception(message, new Exception()), messageStackTrace },
      { new InvocationTargetException(null), "InvocationTargetException (" + getClass().getSimpleName() + ".java:" },
      { new InvocationTargetException(new Exception()), noMessageStackTrace },
      { new InvocationTargetException(new Exception(message)), messageStackTrace },
    };
  }
  @Test(dataProvider = "stackTraceToSingleLineString")
  public void stackTraceToSingleLineString(Throwable t, String startOfOutput)
  {
    assertThat(StaticUtils.stackTraceToSingleLineString(t)).startsWith(startOfOutput);
  }
  @DataProvider
  public Object[][] stackTraceToSingleLineStringInDebugBuild()
  {
    final String message = "This is a tremendous error message";
    final String messageStackTrace = "java.lang.Exception: " + message + " / " + getClass().getSimpleName() + ".java:";
    return new Object[][] {
      { null, "" },
      { new Exception(), "java.lang.Exception / " + getClass().getSimpleName() + ".java:" },
      { new Exception(message), messageStackTrace },
      { new Exception(new Exception()), "java.lang.Exception: java.lang.Exception / " + getClass().getSimpleName() + ".java:" },
      { new Exception(message, new Exception()), messageStackTrace },
    };
  }
  @Test(dataProvider = "stackTraceToSingleLineStringInDebugBuild")
  public void stackTraceToSingleLineStringInDebugBuild(Throwable t, String startOfOutput)
  {
    final boolean orig = DynamicConstants.DEBUG_BUILD;
    DynamicConstants.DEBUG_BUILD = true;
    try
    {
      assertThat(StaticUtils.stackTraceToSingleLineString(t)).startsWith(startOfOutput);
    }
    finally
    {
      DynamicConstants.DEBUG_BUILD = orig;
    }
  }
}