From commits-return-116270-archive-asf-public=cust-asf.ponee.io@ignite.apache.org Thu Jan 11 13:11:00 2018 Return-Path: X-Original-To: archive-asf-public@eu.ponee.io Delivered-To: archive-asf-public@eu.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by mx-eu-01.ponee.io (Postfix) with ESMTP id 8386E180656 for ; Thu, 11 Jan 2018 13:11:00 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 73B38160C1F; Thu, 11 Jan 2018 12:11:00 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 9B3FA160C48 for ; Thu, 11 Jan 2018 13:10:58 +0100 (CET) Received: (qmail 60576 invoked by uid 500); 11 Jan 2018 12:10:57 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 60423 invoked by uid 99); 11 Jan 2018 12:10:57 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 11 Jan 2018 12:10:57 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 0DA43F328A; Thu, 11 Jan 2018 12:10:51 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sboikov@apache.org To: commits@ignite.apache.org Date: Thu, 11 Jan 2018 12:10:52 -0000 Message-Id: In-Reply-To: <8ab8fcf3ca67494297efece28c1fcadb@git.apache.org> References: <8ab8fcf3ca67494297efece28c1fcadb@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [02/17] ignite git commit: ignite-7195: Length limit for GridToStringBuilder ignite-7195: Length limit for GridToStringBuilder Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5d66516d Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5d66516d Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5d66516d Branch: refs/heads/ignite-zk Commit: 5d66516d18b84878331918b79afe452d70bd7a42 Parents: f2edb7e Author: Alexander Belyak Authored: Wed Jan 10 12:03:20 2018 +0300 Committer: sboikov Committed: Wed Jan 10 12:03:20 2018 +0300 ---------------------------------------------------------------------- .../apache/ignite/IgniteSystemProperties.java | 8 + .../util/tostring/CircularStringBuilder.java | 179 +++++++++ .../util/tostring/GridToStringBuilder.java | 359 ++++++++++++++----- .../util/tostring/GridToStringThreadLocal.java | 9 +- .../internal/util/tostring/SBLengthLimit.java | 74 ++++ .../internal/util/tostring/SBLimitedLength.java | 285 +++++++++++++++ .../tostring/CircularStringBuilderSelfTest.java | 69 ++++ .../tostring/GridToStringBuilderSelfTest.java | 116 +++++- .../testsuites/IgniteUtilSelfTestSuite.java | 2 + 9 files changed, 1014 insertions(+), 87 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java index 9732905..ad4835a 100644 --- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java +++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java @@ -158,6 +158,14 @@ public final class IgniteSystemProperties { */ public static final String IGNITE_TO_STRING_INCLUDE_SENSITIVE = "IGNITE_TO_STRING_INCLUDE_SENSITIVE"; + /** Maximum length for {@code toString()} result. */ + public static final String IGNITE_TO_STRING_MAX_LENGTH = "IGNITE_TO_STRING_MAX_LENGTH"; + + /** + * Limit collection (map, array) elements number to output. + */ + public static final String IGNITE_TO_STRING_COLLECTION_LIMIT = "IGNITE_TO_STRING_COLLECTION_LIMIT"; + /** * If this property is set to {@code true} (default) and Ignite is launched * in verbose mode (see {@link #IGNITE_QUIET}) and no console appenders can be found http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java new file mode 100644 index 0000000..4f33724 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java @@ -0,0 +1,179 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.util.tostring; + +/** + * Basic string builder over circular buffer. + */ +public class CircularStringBuilder { + + /** Value */ + private final char value[]; + + /** Last written character idx (-1 if empty). */ + private int finishAt = -1; + + /** Value is full flag. */ + private boolean full; + + /** Number of skipped characters */ + private int skipped = 0; + + /** + * Creates an CircularStringBuilder of the specified capacity. + * + * @param capacity Capacity. + */ + CircularStringBuilder (int capacity) { + assert capacity > 0 : "Can't allocate CircularStringBuilder with capacity: " + capacity; + + value = new char[capacity]; + } + + /** + * Returns the length (character count). + * + * @return the length of the sequence of characters currently + * represented by this object + */ + public int length() { return full ? value.length : finishAt + 1; } + + /** + * Returns the current capacity. + * + * @return the current capacity + */ + public int capacity() { + return value.length; + } + + /** + * Appends the string representation of the {@code Object} argument. + * + * @param obj an {@code Object}. + * @return a reference to this object. + */ + public CircularStringBuilder append(Object obj) { + return append(String.valueOf(obj)); + } + + /** + * Appends the specified string to this character sequence. + * + * @param str a string. + * @return a reference to this object. + */ + public CircularStringBuilder append(String str) { + if (str == null) + return appendNull(); + + int objStrLen = str.length(); + + if (objStrLen >= value.length) { + // String bigger or equal to value length + str.getChars(objStrLen - value.length, objStrLen, value, 0); + + skipped += objStrLen - value.length + finishAt + 1; + + finishAt = value.length - 1; + + full = true; + } + else { + // String smaller then value length + if (value.length - finishAt - 1 < objStrLen) { + // String doesn't fit into remaining part of value array + int firstPart = value.length - finishAt - 1; + + if (firstPart > 0) + str.getChars(0, firstPart, value, finishAt + 1); + + str.getChars(firstPart, objStrLen, value, 0); + + skipped += full ? objStrLen : objStrLen - firstPart; + + finishAt = finishAt + objStrLen - value.length; + } + else { + // Whole string fin into remaining part of value array + str.getChars(0, objStrLen, value, finishAt + 1); + + skipped += full ? objStrLen : 0; + + finishAt += objStrLen; + } + + full = full || finishAt + objStrLen >= value.length - 1; + } + + return this; + } + + /** + * Append StringBuffer + * + * @param sb StringBuffer to append. + * @return Reference to this object. + */ + public CircularStringBuilder append(StringBuffer sb) { + if (sb == null) + return appendNull(); + + int len = sb.length(); + + if (len < value.length) + append(sb.toString()); + else { + skipped += len - value.length; + + append(sb.substring(len - value.length)); + } + + return this; + } + + /** + * @return This builder. + */ + private CircularStringBuilder appendNull() { + append("null"); + + return this; + } + + /** + * @return Count of skipped elements. + */ + public int getSkipped() { return skipped; } + + /** {@inheritDoc} */ + @Override public String toString() { + // Create a copy, don't share the array + if (full) { + char strValue[] = new char[value.length]; + int firstPart = value.length - finishAt - 1; + + System.arraycopy(value, finishAt + 1, strValue, 0, firstPart); + System.arraycopy(value, 0, strValue, firstPart, value.length - firstPart); + + return new String(strValue, 0, strValue.length); + } + else + return new String(value, 0, finishAt + 1); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java index 8d578ac..ab3bb75 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java @@ -20,7 +20,6 @@ package org.apache.ignite.internal.util.tostring; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.internal.util.typedef.F; -import org.apache.ignite.internal.util.typedef.internal.SB; import org.apache.ignite.internal.util.typedef.internal.U; import org.jetbrains.annotations.Nullable; @@ -43,6 +42,7 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_INCLUDE_SENSITIVE; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_COLLECTION_LIMIT; /** * Provides auto-generation framework for {@code toString()} output. @@ -86,14 +86,15 @@ public class GridToStringBuilder { /** */ private static final ReadWriteLock rwLock = new ReentrantReadWriteLock(); - /** Maximum number of collection (map) entries to print. */ - public static final int MAX_COL_SIZE = 200; - /** {@link IgniteSystemProperties#IGNITE_TO_STRING_INCLUDE_SENSITIVE} */ public static final boolean INCLUDE_SENSITIVE = IgniteSystemProperties.getBoolean(IGNITE_TO_STRING_INCLUDE_SENSITIVE, true); /** */ + private static final int COLLECTION_LIMIT = + IgniteSystemProperties.getInteger(IGNITE_TO_STRING_COLLECTION_LIMIT, 100); + + /** */ private static ThreadLocal> threadCache = new ThreadLocal>() { @Override protected Queue initialValue() { Queue queue = new LinkedList<>(); @@ -104,6 +105,14 @@ public class GridToStringBuilder { } }; + /** */ + private static ThreadLocal threadCurLen = new ThreadLocal() { + @Override protected SBLengthLimit initialValue() { + return new SBLengthLimit(); + } + }; + + /** * Produces auto-generated output of string presentation for given object and its declaration class. * @@ -281,11 +290,20 @@ public class GridToStringBuilder { addVals[4] = val4; addSens[4] = sens4; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 5); + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 5); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -363,11 +381,20 @@ public class GridToStringBuilder { addVals[5] = val5; addSens[5] = sens5; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 6); + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 6); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -453,11 +480,20 @@ public class GridToStringBuilder { addVals[6] = val6; addSens[6] = sens6; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 7); + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 7); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -547,11 +583,20 @@ public class GridToStringBuilder { addVals[3] = val3; addSens[3] = sens3; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 4); + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 4); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -630,11 +675,20 @@ public class GridToStringBuilder { addVals[2] = val2; addSens[2] = sens2; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 3); + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 3); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -698,11 +752,20 @@ public class GridToStringBuilder { addVals[1] = val1; addSens[1] = sens1; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 2); + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 2); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -753,11 +816,20 @@ public class GridToStringBuilder { addVals[0] = val; addSens[0] = sens; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 1); + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 1); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -782,12 +854,21 @@ public class GridToStringBuilder { // in each string() apply. GridToStringThreadLocal tmp = queue.isEmpty() ? new GridToStringThreadLocal() : queue.remove(); + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(cls, tmp.getStringBuilder(), obj, tmp.getAdditionalNames(), + newStr = lenLim.length() == 0; + + return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, tmp.getAdditionalNames(), tmp.getAdditionalValues(), null, 0); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -805,6 +886,66 @@ public class GridToStringBuilder { } /** + * Print value with length limitation + * @param buf buffer to print to. + * @param val value to print, can be {@code null}. + */ + private static void toString(SBLimitedLength buf, Object val) { + if (val == null) + buf.a("null"); + else + toString(buf, val.getClass(), val); + } + + /** + * Print value with length limitation + * @param buf buffer to print to. + * @param valClass value class. + * @param val value to print + */ + private static void toString(SBLimitedLength buf, Class valClass, Object val) { + if (valClass.isArray()) + buf.a(arrayToString(valClass, val)); + else { + int overflow = 0; + char bracket = ' '; + + if (val instanceof Collection && ((Collection)val).size() > COLLECTION_LIMIT) { + overflow = ((Collection)val).size() - COLLECTION_LIMIT; + bracket = ']'; + val = F.retain((Collection) val, true, COLLECTION_LIMIT); + } + else if (val instanceof Map && ((Map)val).size() > COLLECTION_LIMIT) { + Map tmp = U.newHashMap(COLLECTION_LIMIT); + + overflow = ((Map)val).size() - COLLECTION_LIMIT; + + bracket= '}'; + + int cntr = 0; + + for (Object o : ((Map)val).entrySet()) { + Map.Entry e = (Map.Entry)o; + + tmp.put(e.getKey(), e.getValue()); + + if (++cntr >= COLLECTION_LIMIT) + break; + } + + val = tmp; + } + + buf.a(val); + + if (overflow > 0) { + buf.d(buf.length() - 1); + buf.a("... and ").a(overflow).a(" more").a(bracket); + } + } + } + + /** * Creates an uniformed string presentation for the given object. * * @param cls Class of the object. @@ -818,7 +959,10 @@ public class GridToStringBuilder { * @param Type of object. */ @SuppressWarnings({"unchecked"}) - private static String toStringImpl(Class cls, SB buf, T obj, + private static String toStringImpl( + Class cls, + SBLimitedLength buf, + T obj, Object[] addNames, Object[] addVals, @Nullable boolean[] addSens, @@ -844,7 +988,7 @@ public class GridToStringBuilder { for (GridToStringFieldDescriptor fd : cd.getFields()) { if (!first) - buf.a(", "); + buf.a(", "); else first = false; @@ -858,31 +1002,7 @@ public class GridToStringBuilder { Class fieldType = field.getType(); - if (fieldType.isArray()) - buf.a(arrayToString(fieldType, field.get(obj))); - else { - Object val = field.get(obj); - - if (val instanceof Collection && ((Collection)val).size() > MAX_COL_SIZE) - val = F.retain((Collection)val, true, MAX_COL_SIZE); - else if (val instanceof Map && ((Map)val).size() > MAX_COL_SIZE) { - Map tmp = U.newHashMap(MAX_COL_SIZE); - int cntr = 0; - - for (Object o : ((Map)val).entrySet()) { - Map.Entry e = (Map.Entry)o; - - tmp.put(e.getKey(), e.getValue()); - - if (++cntr >= MAX_COL_SIZE) - break; - } - - val = tmp; - } - - buf.a(val); - } + toString(buf, fieldType, field.get(obj)); } appendVals(buf, first, addNames, addVals, addSens, addLen); @@ -910,32 +1030,6 @@ public class GridToStringBuilder { } /** - * @param arrType Type of the array. - * @param arr Array object. - * @return String representation of an array. - */ - public static String arrayToString(Class arrType, Object arr) { - if (arrType.equals(byte[].class)) - return Arrays.toString((byte[])arr); - if (arrType.equals(boolean[].class)) - return Arrays.toString((boolean[])arr); - if (arrType.equals(short[].class)) - return Arrays.toString((short[])arr); - if (arrType.equals(int[].class)) - return Arrays.toString((int[])arr); - if (arrType.equals(long[].class)) - return Arrays.toString((long[])arr); - if (arrType.equals(float[].class)) - return Arrays.toString((float[])arr); - if (arrType.equals(double[].class)) - return Arrays.toString((double[])arr); - if (arrType.equals(char[].class)) - return Arrays.toString((char[])arr); - - return Arrays.toString((Object[])arr); - } - - /** * Produces uniformed output of string with context properties * * @param str Output prefix or {@code null} if empty. @@ -948,6 +1042,51 @@ public class GridToStringBuilder { } /** + * @param arrType Type of the array. + * @param arr Array object. + * @return String representation of an array. + */ + @SuppressWarnings({"ConstantConditions", "unchecked"}) + public static String arrayToString(Class arrType, Object arr) { + T[] array = (T[])arr; + + if (array.length > COLLECTION_LIMIT) + arr = Arrays.copyOf(array, COLLECTION_LIMIT); + + String res; + + if (arrType.equals(byte[].class)) + res = Arrays.toString((byte[])arr); + else if (arrType.equals(boolean[].class)) + res = Arrays.toString((boolean[])arr); + else if (arrType.equals(short[].class)) + res = Arrays.toString((short[])arr); + else if (arrType.equals(int[].class)) + res = Arrays.toString((int[])arr); + else if (arrType.equals(long[].class)) + res = Arrays.toString((long[])arr); + else if (arrType.equals(float[].class)) + res = Arrays.toString((float[])arr); + else if (arrType.equals(double[].class)) + res = Arrays.toString((double[])arr); + else if (arrType.equals(char[].class)) + res = Arrays.toString((char[])arr); + else + res = Arrays.toString((Object[])arr); + + if (array.length > COLLECTION_LIMIT) { + StringBuilder resSB = new StringBuilder(res); + + resSB.deleteCharAt(resSB.length() - 1); + resSB.append("... and ").append(array.length - COLLECTION_LIMIT).append(" more]"); + + res = resSB.toString(); + } + + return res; + } + + /** * Produces uniformed output of string with context properties * * @param str Output prefix or {@code null} if empty. @@ -976,11 +1115,20 @@ public class GridToStringBuilder { propVals[0] = val; propSens[0] = sens; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 1); + newStr = lenLim.length() == 0; + + return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 1); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -1037,11 +1185,20 @@ public class GridToStringBuilder { propVals[1] = val1; propSens[1] = sens1; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 2); + newStr = lenLim.length() == 0; + + return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 2); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -1091,11 +1248,20 @@ public class GridToStringBuilder { propVals[2] = val2; propSens[2] = sens2; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 3); + newStr = lenLim.length() == 0; + + return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 3); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -1153,11 +1319,20 @@ public class GridToStringBuilder { propVals[3] = val3; propSens[3] = sens3; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 4); + newStr = lenLim.length() == 0; + + return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 4); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -1223,11 +1398,20 @@ public class GridToStringBuilder { propVals[4] = val4; propSens[4] = sens4; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 5); + newStr = lenLim.length() == 0; + + return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 5); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -1301,11 +1485,20 @@ public class GridToStringBuilder { propVals[5] = val5; propSens[5] = sens5; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 6); + newStr = lenLim.length() == 0; + + return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 6); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -1387,11 +1580,20 @@ public class GridToStringBuilder { propVals[6] = val6; propSens[6] = sens6; + SBLengthLimit lenLim = threadCurLen.get(); + + boolean newStr = false; + try { - return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 7); + newStr = lenLim.length() == 0; + + return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 7); } finally { queue.offer(tmp); + + if (newStr) + lenLim.reset(); } } @@ -1406,7 +1608,7 @@ public class GridToStringBuilder { * @param propCnt Properties count. * @return String presentation of the object. */ - private static String toStringImpl(String str, SB buf, Object[] propNames, Object[] propVals, + private static String toStringImpl(String str, SBLimitedLength buf, Object[] propNames, Object[] propVals, boolean[] propSens, int propCnt) { buf.setLength(0); @@ -1433,7 +1635,7 @@ public class GridToStringBuilder { * @param addSens Sensitive flag of values or {@code null} if all values are not sensitive. * @param addLen How many additional values will be included. */ - private static void appendVals(SB buf, + private static void appendVals(SBLimitedLength buf, boolean first, Object[] addNames, Object[] addVals, @@ -1452,11 +1654,6 @@ public class GridToStringBuilder { if (incAnn != null && incAnn.sensitive() && !INCLUDE_SENSITIVE) continue; - - Class cls = addVal.getClass(); - - if (cls.isArray()) - addVal = arrayToString(cls, addVal); } if (!first) @@ -1464,7 +1661,9 @@ public class GridToStringBuilder { else first = false; - buf.a(addNames[i]).a('=').a(addVal); + buf.a(addNames[i]).a('='); + + toString(buf, addVal); } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java index 8ffacb3..2f62727 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java @@ -17,14 +17,12 @@ package org.apache.ignite.internal.util.tostring; -import org.apache.ignite.internal.util.typedef.internal.SB; - /** * Helper wrapper containing StringBuilder and additional values. Stored as a thread-local variable. */ class GridToStringThreadLocal { /** */ - private SB sb = new SB(256); + private SBLimitedLength sb = new SBLimitedLength(256); /** */ private Object[] addNames = new Object[7]; @@ -36,9 +34,12 @@ class GridToStringThreadLocal { private boolean[] addSens = new boolean[7]; /** + * @param len Length limit. * @return String builder. */ - SB getStringBuilder() { + SBLimitedLength getStringBuilder(SBLengthLimit len) { + sb.initLimit(len); + return sb; } http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java new file mode 100644 index 0000000..2710a85 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.util.tostring; + +import org.apache.ignite.IgniteSystemProperties; + +import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_MAX_LENGTH; + +/** + * + */ +class SBLengthLimit { + /** */ + private static final int MAX_TO_STR_LEN = IgniteSystemProperties.getInteger(IGNITE_TO_STRING_MAX_LENGTH, 10_000); + + /** Length of tail part of message */ + private static final int TAIL_LEN = MAX_TO_STR_LEN / 10 * 2; + + /** */ + private int len; + + /** + * @return Current length. + */ + int length() { + return len; + } + + /** + * + */ + void reset() { + len = 0; + } + + /** + * @param sb String builder. + * @param writtenLen Written length. + */ + void onWrite(SBLimitedLength sb, int writtenLen) { + len += writtenLen; + + if (len > MAX_TO_STR_LEN && sb.getTail() == null) { + CircularStringBuilder tail = new CircularStringBuilder(TAIL_LEN); + + tail.append(sb.impl().substring(MAX_TO_STR_LEN - TAIL_LEN)); + + sb.setTail(tail); + sb.setLength(MAX_TO_STR_LEN - TAIL_LEN); + } + } + + /** + * @return {@code True} if reached limit. + */ + boolean overflowed() { + return len > MAX_TO_STR_LEN; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java new file mode 100644 index 0000000..da6828e --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java @@ -0,0 +1,285 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.util.tostring; + +import org.apache.ignite.internal.util.GridStringBuilder; +import java.util.Arrays; + +/** + * + */ +public class SBLimitedLength extends GridStringBuilder { + /** */ + private SBLengthLimit lenLimit; + + /** Additional string builder to get tail of message. */ + private CircularStringBuilder tail; + + /** + * @param cap Capacity. + */ + SBLimitedLength(int cap) { + super(cap); + } + + /** + * @param lenLimit Length limit. + */ + void initLimit(SBLengthLimit lenLimit) { + this.lenLimit = lenLimit; + tail = null; + } + + /** + * @return tail string builder. + */ + public CircularStringBuilder getTail() { + return tail; + } + + /** + * @param tail tail CircularStringBuilder to set. + */ + public void setTail(CircularStringBuilder tail) { + this.tail = tail; + } + + /** + * @param lenBeforeWrite Length before write. + * @return This builder. + */ + private GridStringBuilder onWrite(int lenBeforeWrite) { + assert lenLimit != null; + + lenLimit.onWrite(this, length() - lenBeforeWrite); + + return this; + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(Object obj) { + if (lenLimit.overflowed()) { + tail.append(obj); + return this; + } + + int curLen = length(); + + super.a(obj); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(String str) { + if (lenLimit.overflowed()) { + tail.append(str); + return this; + } + + int curLen = length(); + + super.a(str); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(StringBuffer sb) { + if (lenLimit.overflowed()) { + tail.append(sb); + return this; + } + + int curLen = length(); + + super.a(sb); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(CharSequence s) { + if (lenLimit.overflowed()) { + tail.append(s); + return this; + } + + int curLen = length(); + + super.a(s); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(CharSequence s, int start, int end) { + if (lenLimit.overflowed()) { + tail.append(s.subSequence(start, end)); + return this; + } + + int curLen = length(); + + super.a(s, start, end); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(char[] str) { + if (lenLimit.overflowed()) { + tail.append(str); + return this; + } + + int curLen = length(); + + super.a(str); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(char[] str, int offset, int len) { + if (lenLimit.overflowed()) { + tail.append(Arrays.copyOfRange(str, offset, len)); + return this; + } + + int curLen = length(); + + super.a(str, offset, len); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(boolean b) { + if (lenLimit.overflowed()) { + tail.append(b); + return this; + } + + int curLen = length(); + + super.a(b); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(char c) { + if (lenLimit.overflowed()) { + tail.append(c); + return this; + } + + int curLen = length(); + + super.a(c); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(int i) { + if (lenLimit.overflowed()) { + tail.append(i); + return this; + } + + int curLen = length(); + + super.a(i); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(long lng) { + if (lenLimit.overflowed()) { + tail.append(lng); + return this; + } + + int curLen = length(); + + super.a(lng); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(float f) { + if (lenLimit.overflowed()) { + tail.append(f); + return this; + } + + int curLen = length(); + + super.a(f); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder a(double d) { + if (lenLimit.overflowed()) { + tail.append(d); + return this; + } + + int curLen = length(); + + super.a(d); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public GridStringBuilder appendCodePoint(int codePoint) { + if (lenLimit.overflowed()) { + tail.append(codePoint); + return this; + } + + int curLen = length(); + + super.appendCodePoint(codePoint); + + return onWrite(curLen); + } + + /** {@inheritDoc} */ + @Override public String toString() { + if (tail == null) + return super.toString(); + else { + int tailLen = tail.length(); + StringBuilder res = new StringBuilder(impl().capacity() + 100); + + res.append(impl()); + res.append("... and ").append(String.valueOf(tail.getSkipped() + tailLen)) + .append(" skipped ...").append(tail.toString()); + + return res.toString(); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java new file mode 100644 index 0000000..b927863 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.ignite.internal.util.tostring; + +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.apache.ignite.testframework.junits.common.GridCommonTest; + +/** + * + */ +@GridCommonTest(group = "Utils") +public class CircularStringBuilderSelfTest extends GridCommonAbstractTest { + /** + * @throws Exception If failed. + */ + public void testCSBPrimitive() throws Exception { + CircularStringBuilder csb = new CircularStringBuilder(1); + csb.append((String)null); + assertEquals("l", csb.toString()); + csb.append('1'); + assertEquals("1", csb.toString()); + + CircularStringBuilder csb2 = new CircularStringBuilder(1); + csb2.append(1); + assertEquals("1", csb2.toString()); + } + + /** + * @throws Exception If failed. + */ + public void testCSBOverflow() throws Exception { + testSB(3, "1234", 2, "234"); + testSB(4, "1234", 2, "1234"); + testSB(5, "1234", 2, "41234"); + testSB(6, "1234", 2, "341234"); + testSB(7, "1234", 2, "2341234"); + testSB(8, "1234", 2, "12341234"); + } + + /** + * @param capacity Capacity. + * @param pattern Pattern to add. + * @param num How many times pattern should be added. + * @param expected Expected string. + */ + private void testSB(int capacity, String pattern, int num, String expected){ + CircularStringBuilder csb = new CircularStringBuilder(capacity); + + for (int i = 0; i < num; i++) + csb.append(pattern); + + assertEquals(expected, csb.toString()); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java index 6a0eae2..9a6b9ef 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java @@ -17,12 +17,18 @@ package org.apache.ignite.internal.util.tostring; +import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.locks.ReadWriteLock; import org.apache.ignite.IgniteLogger; +import org.apache.ignite.IgniteSystemProperties; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_COLLECTION_LIMIT; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_MAX_LENGTH; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.testframework.junits.common.GridCommonTest; @@ -43,7 +49,7 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest { log.info(obj.toStringManual()); log.info(obj.toStringAutomatic()); - assert obj.toStringManual().equals(obj.toStringAutomatic()); + assertEquals (obj.toStringManual(), obj.toStringAutomatic()); } /** @@ -60,7 +66,7 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest { String automatic = obj.toStringWithAdditionalAutomatic(); log.info(automatic); - assert manual.equals(automatic); + assertEquals(manual, automatic); } /** @@ -121,6 +127,92 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest { } /** + * Test array print. + * @param v value to get array class and fill array. + * @param limit value of IGNITE_TO_STRING_COLLECTION_LIMIT. + * @throws Exception if failed. + */ + private void testArr(V v, int limit) throws Exception { + T[] arrOf = (T[]) Array.newInstance(v.getClass(), limit + 1); + Arrays.fill(arrOf, v); + T[] arr = Arrays.copyOf(arrOf, limit); + + String arrStr = GridToStringBuilder.arrayToString(arr.getClass(), arr); + String arrOfStr = GridToStringBuilder.arrayToString(arrOf.getClass(), arrOf); + + // Simulate overflow + StringBuilder resultSB = new StringBuilder(arrStr); + resultSB.deleteCharAt(resultSB.length()-1); + resultSB.append("... and ").append(arrOf.length - limit).append(" more]"); + arrStr = resultSB.toString(); + + assertTrue("Collection limit error in array of type " + arrOf.getClass().getName() + + " error, normal arr: <" + arrStr + ">, overflowed arr: <" + arrOfStr + ">", arrStr.equals(arrOfStr)); + } + + /** + * @throws Exception If failed. + */ + public void testToStringCollectionLimits() throws Exception { + int limit = IgniteSystemProperties.getInteger(IGNITE_TO_STRING_COLLECTION_LIMIT, 100); + + Object vals[] = new Object[] {Byte.MIN_VALUE, Boolean.TRUE, Short.MIN_VALUE, Integer.MIN_VALUE, Long.MIN_VALUE, + Float.MIN_VALUE, Double.MIN_VALUE, Character.MIN_VALUE, new TestClass1()}; + for (Object val : vals) + testArr(val, limit); + + Map strMap = new TreeMap<>(); + List strList = new ArrayList<>(limit+1); + + TestClass1 testClass = new TestClass1(); + testClass.strMap = strMap; + testClass.strListIncl = strList; + + for (int i = 0; i < limit; i++) { + strMap.put("k" + i, "v"); + strList.add("e"); + } + String testClassStr = GridToStringBuilder.toString(TestClass1.class, testClass); + + strMap.put("kz", "v"); // important to add last element in TreeMap here + strList.add("e"); + + String testClassStrOf = GridToStringBuilder.toString(TestClass1.class, testClass); + + String testClassStrOfR = testClassStrOf.replaceAll("... and 1 more",""); + + assertTrue("Collection limit error in Map or List, normal: <" + testClassStr + ">, overflowed: <" + +"testClassStrOf", testClassStr.length() == testClassStrOfR.length()); + + } + + /** + * @throws Exception If failed. + */ + public void testToStringSizeLimits() throws Exception { + + int limit = IgniteSystemProperties.getInteger(IGNITE_TO_STRING_MAX_LENGTH, 10_000); + int tailLen = limit / 10 * 2; + StringBuilder sb = new StringBuilder(limit + 10); + for (int i = 0; i < limit - 100; i++) { + sb.append('a'); + } + String actual = GridToStringBuilder.toString(TestClass2.class, new TestClass2(sb.toString())); + String expected = "TestClass2 [str=" + sb.toString() + "]"; + assertEquals(expected, actual); + + for (int i = 0; i < 100; i++) { + sb.append('b'); + } + actual = GridToStringBuilder.toString(TestClass2.class, new TestClass2(sb.toString())); + expected = "TestClass2 [str=" + sb.toString() + "]"; + assertEquals(expected.substring(0, limit - tailLen), actual.substring(0, limit - tailLen)); + assertEquals(expected.substring(expected.length() - tailLen), actual.substring(actual.length() - tailLen)); + assertTrue(actual.contains("... and")); + assertTrue(actual.contains("skipped ...")); + } + + /** * Test class. */ private static class TestClass1 { @@ -170,6 +262,12 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest { /** */ @SuppressWarnings("unused") + @GridToStringInclude + private List strListIncl; + + + /** */ + @SuppressWarnings("unused") private final Object obj = new Object(); /** */ @@ -193,7 +291,8 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest { buf.append("byteVar=").append(byteVar).append(", "); buf.append("name=").append(name).append(", "); buf.append("finalInt=").append(finalInt).append(", "); - buf.append("strMap=").append(strMap); + buf.append("strMap=").append(strMap).append(", "); + buf.append("strListIncl=").append(strListIncl); buf.append("]"); @@ -227,4 +326,15 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest { return s.toString(); } } + + private static class TestClass2{ + /** */ + @SuppressWarnings("unused") + @GridToStringInclude + private String str; + + public TestClass2(String str) { + this.str = str; + } + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java index 20f37f7..7c99817 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java @@ -33,6 +33,7 @@ import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMapSelfTest; import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemorySelfTest; import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafePartitionedMapSelfTest; import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeStripedLruSefTest; +import org.apache.ignite.internal.util.tostring.CircularStringBuilderSelfTest; import org.apache.ignite.internal.util.tostring.GridToStringBuilderSelfTest; import org.apache.ignite.lang.GridByteArrayListSelfTest; import org.apache.ignite.spi.discovery.ClusterMetricsSnapshotSerializeSelfTest; @@ -76,6 +77,7 @@ public class IgniteUtilSelfTestSuite extends TestSuite { suite.addTestSuite(GridQueueSelfTest.class); suite.addTestSuite(GridStringBuilderFactorySelfTest.class); suite.addTestSuite(GridToStringBuilderSelfTest.class); + suite.addTestSuite(CircularStringBuilderSelfTest.class); suite.addTestSuite(GridByteArrayListSelfTest.class); suite.addTestSuite(GridMBeanSelfTest.class); suite.addTestSuite(GridMBeanDisableSelfTest.class);