diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ResourceBanner.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ResourceBanner.java index 11d9991ed0..d2df72e256 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ResourceBanner.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ResourceBanner.java @@ -28,7 +28,6 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.ansi.Ansi256PropertySource; import org.springframework.boot.ansi.AnsiPropertySource; import org.springframework.core.env.Environment; import org.springframework.core.env.MapPropertySource; @@ -82,7 +81,6 @@ public class ResourceBanner implements Banner { resolvers.add(environment); resolvers.add(getVersionResolver(sourceClass)); resolvers.add(getAnsiResolver()); - resolvers.add(getAnsi256Resolver()); resolvers.add(getTitleResolver(sourceClass)); return resolvers; } @@ -126,12 +124,6 @@ public class ResourceBanner implements Banner { return new PropertySourcesPropertyResolver(sources); } - private PropertyResolver getAnsi256Resolver() { - MutablePropertySources sources = new MutablePropertySources(); - sources.addFirst(new Ansi256PropertySource("ansi256")); - return new PropertySourcesPropertyResolver(sources); - } - private PropertyResolver getTitleResolver(Class sourceClass) { MutablePropertySources sources = new MutablePropertySources(); String applicationTitle = getApplicationTitle(sourceClass); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi256Color.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi256Color.java deleted file mode 100644 index e93f166602..0000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi256Color.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * 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 - * - * https://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.springframework.boot.ansi; - -/** - * {@link AnsiElement} implementation for Ansi 256 colors. - *

- * use {@link Ansi256Color.Foreground} or {@link Ansi256Color.Background} as a concrete - * class. - * - * @author Toshiaki Maki - * @since 2.2.0 - */ -public abstract class Ansi256Color implements AnsiElement { - - /** - * color code - */ - final int colorCode; - - /** - * @param colorCode color code (must be 0-255) - * @throws IllegalArgumentException if color code is not between 0 and 255. - */ - Ansi256Color(int colorCode) { - if (colorCode < 0 || colorCode > 255) { - throw new IllegalArgumentException("'colorCode' must be between 0 and 255."); - } - this.colorCode = colorCode; - } - - /** - * {@link Ansi256Color} foreground colors. - * - * @author Toshiaki Maki - * @since 2.2.0 - */ - public static class Foreground extends Ansi256Color { - - public Foreground(int colorCode) { - super(colorCode); - } - - @Override - public String toString() { - return "38;5;" + super.colorCode; - } - - } - - /** - * {@link Ansi256Color} background colors. - * - * @author Toshiaki Maki - * @since 2.2.0 - */ - public static class Background extends Ansi256Color { - - public Background(int colorCode) { - super(colorCode); - } - - @Override - public String toString() { - return "48;5;" + super.colorCode; - } - - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi256PropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi256PropertySource.java deleted file mode 100644 index 0420d2de6e..0000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi256PropertySource.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * 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 - * - * https://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.springframework.boot.ansi; - -import org.springframework.core.env.PropertyResolver; -import org.springframework.core.env.PropertySource; -import org.springframework.util.StringUtils; - -/** - * {@link PropertyResolver} for {@link Ansi256Color.Background} and - * {@link Ansi256Color.Foreground} elements. Supports properties of the form - * {@code Ansi256Color.Foreground_N} and {@code Ansi256Color.Background_N} ({@code N} must - * be between 0 and 255). - * - * @author Toshiaki Maki - * @since 2.2.0 - */ -public class Ansi256PropertySource extends PropertySource { - - private static final String PREFIX = "Ansi256Color."; - - private static final String FOREGROUND_PREFIX = PREFIX + "Foreground_"; - - private static final String BACKGROUND_PREFIX = PREFIX + "Background_"; - - /** - * Create a new {@link Ansi256PropertySource} instance. - * @param name the name of the property source - */ - public Ansi256PropertySource(String name) { - super(name); - } - - @Override - public Object getProperty(String name) { - if (StringUtils.hasLength(name)) { - if (name.startsWith(FOREGROUND_PREFIX)) { - final int colorCode = Integer.parseInt(name.substring(FOREGROUND_PREFIX.length())); - return AnsiOutput.encode(new Ansi256Color.Foreground(colorCode)); - } - else if (name.startsWith(BACKGROUND_PREFIX)) { - final int colorCode = Integer.parseInt(name.substring(BACKGROUND_PREFIX.length())); - return AnsiOutput.encode(new Ansi256Color.Background(colorCode)); - } - } - return null; - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi8BitColor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi8BitColor.java new file mode 100644 index 0000000000..2b926383f8 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/Ansi8BitColor.java @@ -0,0 +1,88 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.springframework.boot.ansi; + +import org.springframework.util.Assert; + +/** + * {@link AnsiElement} implementation for ANSI 8-bit foreground or background color codes. + * + * @author Toshiaki Maki + * @author Phillip Webb + * @since 2.2.0 + * @see #foreground(int) + * @see #background(int) + */ +public final class Ansi8BitColor implements AnsiElement { + + private final String prefix; + + private final int code; + + /** + * Create a new {@link Ansi8BitColor} instance. + * @param prefix the prefix escape chars + * @param code color code (must be 0-255) + * @throws IllegalArgumentException if color code is not between 0 and 255. + */ + private Ansi8BitColor(String prefix, int code) { + Assert.isTrue(code >= 0 && code <= 255, "Code must be between 0 and 255"); + this.prefix = prefix; + this.code = code; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + Ansi8BitColor other = (Ansi8BitColor) obj; + return this.prefix.equals(other.prefix) && this.code == other.code; + } + + @Override + public int hashCode() { + return this.prefix.hashCode() * 31 + this.code; + } + + @Override + public String toString() { + return this.prefix + this.code; + } + + /** + * Return a foreground ANSI color code instance for the given code. + * @param code the color code + * @return an ANSI color code instance + */ + public static Ansi8BitColor foreground(int code) { + return new Ansi8BitColor("38;5;", code); + } + + /** + * Return a background ANSI color code instance for the given code. + * @param code the color code + * @return an ANSI color code instance + */ + public static Ansi8BitColor background(int code) { + return new Ansi8BitColor("48;5;", code); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java index cba03f984a..4c0cce7d18 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java @@ -21,34 +21,43 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Set; +import java.util.function.IntFunction; import org.springframework.core.env.PropertyResolver; import org.springframework.core.env.PropertySource; import org.springframework.util.StringUtils; /** - * {@link PropertyResolver} for {@link AnsiStyle}, {@link AnsiColor} and - * {@link AnsiBackground} elements. Supports properties of the form - * {@code AnsiStyle.BOLD}, {@code AnsiColor.RED} or {@code AnsiBackground.GREEN}. Also - * supports a prefix of {@code Ansi.} which is an aggregation of everything (with + * {@link PropertyResolver} for {@link AnsiStyle}, {@link AnsiColor}, + * {@link AnsiBackground} and {@link Ansi8BitColor} elements. Supports properties of the + * form {@code AnsiStyle.BOLD}, {@code AnsiColor.RED} or {@code AnsiBackground.GREEN}. + * Also supports a prefix of {@code Ansi.} which is an aggregation of everything (with * background colors prefixed {@code BG_}). + *

+ * ANSI 8-bit color codes can be used with {@code AnsiColor} and {@code AnsiBackground}. + * For example, {@code AnsiColor.208} will render orange text. + * Wikipedia has a complete + * list of the 8-bit color codes that can be used. * * @author Phillip Webb + * @author Toshiaki Maki * @since 1.3.0 */ public class AnsiPropertySource extends PropertySource { - private static final Iterable> MAPPED_ENUMS; + private static final Iterable MAPPINGS; static { - List> enums = new ArrayList<>(); - enums.add(new MappedEnum<>("AnsiStyle.", AnsiStyle.class)); - enums.add(new MappedEnum<>("AnsiColor.", AnsiColor.class)); - enums.add(new MappedEnum<>("AnsiBackground.", AnsiBackground.class)); - enums.add(new MappedEnum<>("Ansi.", AnsiStyle.class)); - enums.add(new MappedEnum<>("Ansi.", AnsiColor.class)); - enums.add(new MappedEnum<>("Ansi.BG_", AnsiBackground.class)); - MAPPED_ENUMS = Collections.unmodifiableList(enums); + List mappings = new ArrayList<>(); + mappings.add(new EnumMapping<>("AnsiStyle.", AnsiStyle.class)); + mappings.add(new EnumMapping<>("AnsiColor.", AnsiColor.class)); + mappings.add(new Ansi8BitColorMapping("AnsiColor.", Ansi8BitColor::foreground)); + mappings.add(new EnumMapping<>("AnsiBackground.", AnsiBackground.class)); + mappings.add(new Ansi8BitColorMapping("AnsiBackground.", Ansi8BitColor::background)); + mappings.add(new EnumMapping<>("Ansi.", AnsiStyle.class)); + mappings.add(new EnumMapping<>("Ansi.", AnsiColor.class)); + mappings.add(new EnumMapping<>("Ansi.BG_", AnsiBackground.class)); + MAPPINGS = Collections.unmodifiableList(mappings); } private final boolean encode; @@ -66,16 +75,13 @@ public class AnsiPropertySource extends PropertySource { @Override public Object getProperty(String name) { if (StringUtils.hasLength(name)) { - for (MappedEnum mappedEnum : MAPPED_ENUMS) { - if (name.startsWith(mappedEnum.getPrefix())) { - String enumName = name.substring(mappedEnum.getPrefix().length()); - for (Enum ansiEnum : mappedEnum.getEnums()) { - if (ansiEnum.name().equals(enumName)) { - if (this.encode) { - return AnsiOutput.encode((AnsiElement) ansiEnum); - } - return ansiEnum; - } + for (Mapping mapping : MAPPINGS) { + String prefix = mapping.getPrefix(); + if (name.startsWith(prefix)) { + String postfix = name.substring(prefix.length()); + AnsiElement element = mapping.getElement(postfix); + if (element != null) { + return (this.encode) ? AnsiOutput.encode(element) : element; } } } @@ -84,26 +90,79 @@ public class AnsiPropertySource extends PropertySource { } /** - * Mapping between an enum and the pseudo property source. + * Mapping between a name and the pseudo property source. */ - private static class MappedEnum> { + private abstract static class Mapping { private final String prefix; - private final Set enums; - - MappedEnum(String prefix, Class enumType) { + Mapping(String prefix) { this.prefix = prefix; - this.enums = EnumSet.allOf(enumType); - } String getPrefix() { return this.prefix; } - Set getEnums() { - return this.enums; + abstract AnsiElement getElement(String postfix); + + } + + /** + * {@link Mapping} for {@link AnsiElement} enums. + */ + private static class EnumMapping & AnsiElement> extends Mapping { + + private final Set enums; + + EnumMapping(String prefix, Class enumType) { + super(prefix); + this.enums = EnumSet.allOf(enumType); + } + + @Override + AnsiElement getElement(String postfix) { + for (Enum candidate : this.enums) { + if (candidate.name().equals(postfix)) { + return (AnsiElement) candidate; + } + } + return null; + } + + } + + /** + * {@link Mapping} for {@link Ansi8BitColor}. + */ + private static class Ansi8BitColorMapping extends Mapping { + + private final IntFunction factory; + + Ansi8BitColorMapping(String prefix, IntFunction factory) { + super(prefix); + this.factory = factory; + } + + @Override + AnsiElement getElement(String postfix) { + if (containsOnlyDigits(postfix)) { + try { + return this.factory.apply(Integer.parseInt(postfix)); + } + catch (IllegalArgumentException ex) { + } + } + return null; + } + + private boolean containsOnlyDigits(String postfix) { + for (int i = 0; i < postfix.length(); i++) { + if (!Character.isDigit(postfix.charAt(i))) { + return false; + } + } + return postfix.length() > 0; } } diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 613e4a15a1..2c6dc89d54 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -47,6 +47,12 @@ "description": "Whether images should be inverted for dark terminal themes.", "defaultValue": false }, + { + "name": "spring.banner.image.bitdepth", + "type": "java.lang.Integer", + "description": "The bit depth to use for ANSI colors. Supported values are 4 (16 color) or 8 (256 color).", + "defaultValue": 4 + }, { "name": "debug", "type": "java.lang.Boolean", diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ImageBannerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ImageBannerTests.java index 59a6e992d1..8c314816fc 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ImageBannerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ImageBannerTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.boot.ansi.Ansi8BitColor; import org.springframework.boot.ansi.AnsiBackground; import org.springframework.boot.ansi.AnsiColor; import org.springframework.boot.ansi.AnsiOutput; @@ -168,6 +169,16 @@ class ImageBannerTests { assertThat(lines).hasSize(frames * linesPerFrame - 1); } + @Test + void printBannerWhenBitDepthIs8ShouldUseColors() { + String banner = printBanner("colors.gif", "spring.banner.image.bitdepth=8"); + assertThat(banner.contains(AnsiOutput.encode(Ansi8BitColor.foreground(124)))); + assertThat(banner.contains(AnsiOutput.encode(Ansi8BitColor.foreground(130)))); + assertThat(banner.contains(AnsiOutput.encode(Ansi8BitColor.foreground(19)))); + assertThat(banner.contains(AnsiOutput.encode(Ansi8BitColor.foreground(127)))); + assertThat(banner.contains(AnsiOutput.encode(Ansi8BitColor.foreground(37)))); + } + private int getBannerHeight(String banner) { return banner.split(System.lineSeparator()).length - 3; } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ResourceBannerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ResourceBannerTests.java index 39234e5bd7..e7aa375bb2 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ResourceBannerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ResourceBannerTests.java @@ -98,8 +98,7 @@ class ResourceBannerTests { @Test void renderWith256Colors() { - Resource resource = new ByteArrayResource( - "${Ansi256Color.Foreground_208}This is orange.${Ansi.NORMAL}".getBytes()); + Resource resource = new ByteArrayResource("${AnsiColor.208}This is orange.${Ansi.NORMAL}".getBytes()); AnsiOutput.setEnabled(AnsiOutput.Enabled.ALWAYS); String banner = printBanner(resource, null, null, null); assertThat(banner).startsWith("\033[38;5;208mThis is orange.\u001B[0m"); @@ -107,8 +106,7 @@ class ResourceBannerTests { @Test void renderWith256ColorsButDisabled() { - Resource resource = new ByteArrayResource( - "${Ansi256Color.Foreground_208}This is orange.${Ansi.NORMAL}".getBytes()); + Resource resource = new ByteArrayResource("${AnsiColor.208}This is orange.${Ansi.NORMAL}".getBytes()); AnsiOutput.setEnabled(AnsiOutput.Enabled.NEVER); String banner = printBanner(resource, null, null, null); assertThat(banner).startsWith("This is orange."); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi256ColorTest.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi256ColorTest.java deleted file mode 100644 index bc32ea9c6f..0000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi256ColorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * 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 - * - * https://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.springframework.boot.ansi; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; - -/** - * Tests for {@link Ansi256Color}. - * - * @author Toshiaki Maki - */ -class Ansi256ColorTest { - - @Test - void testForeground() { - final Ansi256Color ansi256Color = new Ansi256Color.Foreground(208); - assertThat(ansi256Color.toString()).isEqualTo("38;5;208"); - } - - @Test - void testBackground() { - final Ansi256Color ansi256Color = new Ansi256Color.Background(208); - assertThat(ansi256Color.toString()).isEqualTo("48;5;208"); - } - - @Test - void testIllegalColorCode() { - try { - new Ansi256Color.Foreground(256); - failBecauseExceptionWasNotThrown(IllegalArgumentException.class); - } - catch (IllegalArgumentException ex) { - assertThat(ex.getMessage()).isEqualTo("'colorCode' must be between 0 and 255."); - } - } - -} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi256PropertySourceTest.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi256PropertySourceTest.java deleted file mode 100644 index 5fcad0d36f..0000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi256PropertySourceTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * 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 - * - * https://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.springframework.boot.ansi; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link Ansi256PropertySource}. - * - * @author Toshiaki Maki - */ -class Ansi256PropertySourceTest { - - private Ansi256PropertySource source = new Ansi256PropertySource("ansi256"); - - @AfterEach - void reset() { - AnsiOutput.setEnabled(AnsiOutput.Enabled.DETECT); - } - - @Test - void getPropertyShouldConvertAnsi256ColorForeground() { - AnsiOutput.setEnabled(AnsiOutput.Enabled.ALWAYS); - final Object property = this.source.getProperty("Ansi256Color.Foreground_100"); - assertThat(property).isEqualTo("\033[38;5;100m"); - } - - @Test - void getPropertyShouldConvertAnsi256ColorBackground() { - AnsiOutput.setEnabled(AnsiOutput.Enabled.ALWAYS); - final Object property = this.source.getProperty("Ansi256Color.Background_100"); - assertThat(property).isEqualTo("\033[48;5;100m"); - } - - @Test - void getMissingPropertyShouldReturnNull() { - AnsiOutput.setEnabled(AnsiOutput.Enabled.ALWAYS); - final Object property = this.source.getProperty("Ansi256Color.ForeGround_100"); - assertThat(property).isNull(); - } - -} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi8BitColorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi8BitColorTests.java new file mode 100644 index 0000000000..661e664e6a --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/Ansi8BitColorTests.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * 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 + * + * https://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.springframework.boot.ansi; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +/** + * Tests for {@link Ansi8BitColor}. + * + * @author Toshiaki Maki + * @author Phillip Webb + */ +class Ansi8BitColorTests { + + @Test + void toStringWhenForegroundAddsCorrectPrefix() { + assertThat(Ansi8BitColor.foreground(208).toString()).isEqualTo("38;5;208"); + } + + @Test + void toStringWhenBackgroundAddsCorrectPrefix() { + assertThat(Ansi8BitColor.background(208).toString()).isEqualTo("48;5;208"); + } + + @Test + void forgroundWhenOutsideBoundsThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> Ansi8BitColor.foreground(-1)) + .withMessage("Code must be between 0 and 255"); + assertThatIllegalArgumentException().isThrownBy(() -> Ansi8BitColor.foreground(256)) + .withMessage("Code must be between 0 and 255"); + } + + @Test + void backgroundWhenOutsideBoundsThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> Ansi8BitColor.background(-1)) + .withMessage("Code must be between 0 and 255"); + assertThatIllegalArgumentException().isThrownBy(() -> Ansi8BitColor.background(256)) + .withMessage("Code must be between 0 and 255"); + } + + @Test + void equalsAndHashCode() { + Ansi8BitColor one = Ansi8BitColor.foreground(123); + Ansi8BitColor two = Ansi8BitColor.foreground(123); + Ansi8BitColor three = Ansi8BitColor.background(123); + assertThat(one.hashCode()).isEqualTo(two.hashCode()); + assertThat(one).isEqualTo(one).isEqualTo(two).isNotEqualTo(three).isNotEqualTo(null).isNotEqualTo("foo"); + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiPropertySourceTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiPropertySourceTests.java index 26cb59820e..25880cf6be 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiPropertySourceTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiPropertySourceTests.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link AnsiPropertySource}. * * @author Phillip Webb + * @author Toshiaki Maki */ class AnsiPropertySourceTests { @@ -45,11 +46,13 @@ class AnsiPropertySourceTests { @Test void getAnsiColor() { assertThat(this.source.getProperty("AnsiColor.RED")).isEqualTo(AnsiColor.RED); + assertThat(this.source.getProperty("AnsiColor.100")).isEqualTo(Ansi8BitColor.foreground(100)); } @Test void getAnsiBackground() { assertThat(this.source.getProperty("AnsiBackground.GREEN")).isEqualTo(AnsiBackground.GREEN); + assertThat(this.source.getProperty("AnsiBackground.100")).isEqualTo(Ansi8BitColor.background(100)); } @Test @@ -69,6 +72,8 @@ class AnsiPropertySourceTests { AnsiOutput.setEnabled(Enabled.ALWAYS); AnsiPropertySource source = new AnsiPropertySource("ansi", true); assertThat(source.getProperty("Ansi.RED")).isEqualTo("\033[31m"); + assertThat(source.getProperty("AnsiColor.100")).isEqualTo("\033[38;5;100m"); + assertThat(source.getProperty("AnsiBackground.100")).isEqualTo("\033[48;5;100m"); } @Test @@ -76,6 +81,8 @@ class AnsiPropertySourceTests { AnsiOutput.setEnabled(Enabled.NEVER); AnsiPropertySource source = new AnsiPropertySource("ansi", true); assertThat(source.getProperty("Ansi.RED")).isEqualTo(""); + assertThat(source.getProperty("AnsiColor.100")).isEqualTo(""); + assertThat(source.getProperty("AnsiBackground.100")).isEqualTo(""); } }