package org.apache.logging.log4j.core.layout;/*
 * 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.
 */

import java.nio.charset.Charset;

import org.apache.logging.log4j.core.LogEvent;
import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Tests AbstractStringLayout.
 */
public class AbstractStringLayoutTest {
    static class ConcreteStringLayout extends AbstractStringLayout {
        public static int DEFAULT_STRING_BUILDER_SIZE = AbstractStringLayout.DEFAULT_STRING_BUILDER_SIZE;
        public static int MAX_STRING_BUILDER_SIZE = AbstractStringLayout.MAX_STRING_BUILDER_SIZE;

        public ConcreteStringLayout() {
            super(Charset.defaultCharset());
        }

        public static StringBuilder getStringBuilder() {
            return AbstractStringLayout.getStringBuilder();
        }

        @Override
        public String toSerializable(final LogEvent event) {
            return null;
        }
    }

    @Test
    public void testGetStringBuilderCapacityRestrictedToMax() throws Exception {
        final StringBuilder sb = ConcreteStringLayout.getStringBuilder();
        assertEquals("initial capacity", ConcreteStringLayout.DEFAULT_STRING_BUILDER_SIZE, sb.capacity());

        final int MEDIUM = ConcreteStringLayout.DEFAULT_STRING_BUILDER_SIZE + 100;
        final String mediumMessage = new String(new char[MEDIUM]);
        sb.append(mediumMessage);
        final int GROWN = sb.capacity();
        assertTrue("capacity has grown", GROWN >= MEDIUM);
        assertEquals("length=msg length", MEDIUM, sb.length());

        final int LARGE = 4096;
        final String largeMessage = new String(new char[LARGE]);
        final StringBuilder sb2 = ConcreteStringLayout.getStringBuilder();
        assertTrue("reset capacity", sb2.capacity() <= AbstractStringLayout.MAX_STRING_BUILDER_SIZE);
        assertEquals("empty, ready for use", 0, sb2.length());
        sb2.append(largeMessage);
        assertTrue("capacity grown to fit msg length", sb2.capacity() >= LARGE);
        assertEquals("length=msg length", LARGE, sb2.length());

        sb2.setLength(0);
        assertEquals("empty, cleared", 0, sb2.length());
        final StringBuilder next = ConcreteStringLayout.getStringBuilder();
        assertEquals("max capacity", ConcreteStringLayout.MAX_STRING_BUILDER_SIZE, next.capacity());
        assertEquals("empty, ready for use", 0, next.length());
    }
}
@@ -1835,32 +1835,77 @@
 tringBuilder();%0A
+        int initialCapacity = sb.capacity();%0A
         assertEq
@@ -2018,67 +2018,15 @@
 int 
-MEDIUM = ConcreteStringLayout.DEFAULT_STRING_BUILDER_SIZE +
+SMALL =
  100
@@ -2084,22 +2084,21 @@
 ew char%5B
-MEDIUM
+SMALL
 %5D);%0A    
@@ -2131,49 +2131,8 @@
 e);%0A
-        final int GROWN = sb.capacity();%0A
     
@@ -2160,11 +2160,11 @@
 ity 
-has
+not
  gro
@@ -2172,23 +2172,40 @@
 n%22, 
-GROWN %3E= MEDIUM
+sb.capacity() == initialCapacity
 );%0A 
@@ -2249,14 +2249,13 @@
 h%22, 
-MEDIUM
+SMALL
 , sb
@@ -2285,328 +2285,304 @@
 nal 
-int LARGE = 4096;%0A        final String largeMessage = new String(new char%5BLARGE%5D);%0A        final StringBuilder sb2 = ConcreteStringLayout.getStringBuilder();%0A        assertTrue(%22reset capacity%22, sb2.capacity() %3C= AbstractStringLayout.MAX_STRING_BUILDER_SIZE);%0A        assertEquals(%22empty, ready for use%22, 0, sb2.length()
+StringBuilder sb2 = ConcreteStringLayout.getStringBuilder();%0A        assertEquals(%22capacity unchanged%22, sb2.capacity(), initialCapacity);%0A        assertEquals(%22empty, ready for use%22, 0, sb2.length());%0A%0A        final int LARGE = 4096;%0A        final String largeMessage = new String(new char%5BLARGE%5D
 );%0A 
@@ -2695,16 +2695,143 @@
 LARGE);%0A
+        assertTrue(%22capacity is now greater than max length%22, sb2.capacity() %3E= ConcreteStringLayout.MAX_STRING_BUILDER_SIZE);%0A
         
@@ -2878,33 +2878,32 @@
  sb2.length());%0A
-%0A
         sb2.setL
@@ -2911,16 +2911,54 @@
 ngth(0);
+ // set 0 before next getStringBuilder
 %0A       
@@ -2999,32 +2999,148 @@
  sb2.length());%0A
+        assertTrue(%22capacity remains very large%22, sb2.capacity() %3E= ConcreteStringLayout.MAX_STRING_BUILDER_SIZE);%0A%0A
         final St
@@ -3225,20 +3225,16 @@
 ls(%22
-max 
 capacity
 %22, C
@@ -3221,32 +3221,68 @@
 Equals(%22capacity
+, trimmed to MAX_STRING_BUILDER_SIZE
 %22, ConcreteStrin

update test case upon advices from reviewer