1 /* 2 * Copyright (C) 2009 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.escape; 18 19 import com.google.common.annotations.GwtCompatible; 20 import com.google.common.collect.ImmutableMap; 21 import com.google.common.escape.testing.EscaperAsserts; 22 import java.io.IOException; 23 import junit.framework.TestCase; 24 25 /** @author David Beaumont */ 26 @GwtCompatible 27 public class EscapersTest extends TestCase { testNullEscaper()28 public void testNullEscaper() throws IOException { 29 Escaper escaper = Escapers.nullEscaper(); 30 EscaperAsserts.assertBasic(escaper); 31 String s = "\0\n\t\\az09~\uD800\uDC00\uFFFF"; 32 assertEquals("null escaper should have no effect", s, escaper.escape(s)); 33 } 34 testBuilderInitialStateNoReplacement()35 public void testBuilderInitialStateNoReplacement() { 36 // Unsafe characters aren't modified by default (unsafeReplacement == null). 37 Escaper escaper = Escapers.builder().setSafeRange('a', 'z').build(); 38 assertEquals("The Quick Brown Fox", escaper.escape("The Quick Brown Fox")); 39 } 40 testBuilderInitialStateNoneUnsafe()41 public void testBuilderInitialStateNoneUnsafe() { 42 // No characters are unsafe by default (safeMin == 0, safeMax == 0xFFFF). 43 Escaper escaper = Escapers.builder().setUnsafeReplacement("X").build(); 44 assertEquals("\0\uFFFF", escaper.escape("\0\uFFFF")); 45 } 46 testBuilderRetainsState()47 public void testBuilderRetainsState() { 48 // Setting a safe range and unsafe replacement works as expected. 49 Escapers.Builder builder = Escapers.builder(); 50 builder.setSafeRange('a', 'z'); 51 builder.setUnsafeReplacement("X"); 52 assertEquals("XheXXuickXXrownXXoxX", builder.build().escape("The Quick Brown Fox!")); 53 // Explicit replacements take priority over unsafe characters. 54 builder.addEscape(' ', "_"); 55 builder.addEscape('!', "_"); 56 assertEquals("Xhe_Xuick_Xrown_Xox_", builder.build().escape("The Quick Brown Fox!")); 57 // Explicit replacements take priority over safe characters. 58 builder.setSafeRange(' ', '~'); 59 assertEquals("The_Quick_Brown_Fox_", builder.build().escape("The Quick Brown Fox!")); 60 } 61 testBuilderCreatesIndependentEscapers()62 public void testBuilderCreatesIndependentEscapers() { 63 // Setup a simple builder and create the first escaper. 64 Escapers.Builder builder = Escapers.builder(); 65 builder.setSafeRange('a', 'z'); 66 builder.setUnsafeReplacement("X"); 67 builder.addEscape(' ', "_"); 68 Escaper first = builder.build(); 69 // Modify one of the existing mappings before creating a new escaper. 70 builder.addEscape(' ', "-"); 71 builder.addEscape('!', "$"); 72 Escaper second = builder.build(); 73 // This should have no effect on existing escapers. 74 builder.addEscape(' ', "*"); 75 76 // Test both escapers after modifying the builder. 77 assertEquals("Xhe_Xuick_Xrown_XoxX", first.escape("The Quick Brown Fox!")); 78 assertEquals("Xhe-Xuick-Xrown-Xox$", second.escape("The Quick Brown Fox!")); 79 } 80 testAsUnicodeEscaper()81 public void testAsUnicodeEscaper() throws IOException { 82 CharEscaper charEscaper = 83 createSimpleCharEscaper( 84 ImmutableMap.<Character, char[]>builder() 85 .put('x', "<hello>".toCharArray()) 86 .put('\uD800', "<hi>".toCharArray()) 87 .put('\uDC00', "<lo>".toCharArray()) 88 .build()); 89 UnicodeEscaper unicodeEscaper = Escapers.asUnicodeEscaper(charEscaper); 90 EscaperAsserts.assertBasic(unicodeEscaper); 91 assertEquals("<hello><hi><lo>", charEscaper.escape("x\uD800\uDC00")); 92 assertEquals("<hello><hi><lo>", unicodeEscaper.escape("x\uD800\uDC00")); 93 94 // Test that wrapped escapers acquire good Unicode semantics. 95 assertEquals("<hi><hello><lo>", charEscaper.escape("\uD800x\uDC00")); 96 try { 97 unicodeEscaper.escape("\uD800x\uDC00"); 98 fail("should have failed for bad Unicode input"); 99 } catch (IllegalArgumentException e) { 100 // pass 101 } 102 assertEquals("<lo><hi>", charEscaper.escape("\uDC00\uD800")); 103 try { 104 unicodeEscaper.escape("\uDC00\uD800"); 105 fail("should have failed for bad Unicode input"); 106 } catch (IllegalArgumentException e) { 107 // pass 108 } 109 } 110 111 // A trival non-optimized escaper for testing. createSimpleCharEscaper(final ImmutableMap<Character, char[]> replacementMap)112 static CharEscaper createSimpleCharEscaper(final ImmutableMap<Character, char[]> replacementMap) { 113 return new CharEscaper() { 114 @Override 115 protected char[] escape(char c) { 116 return replacementMap.get(c); 117 } 118 }; 119 } 120 121 // A trival non-optimized escaper for testing. 122 static UnicodeEscaper createSimpleUnicodeEscaper( 123 final ImmutableMap<Integer, char[]> replacementMap) { 124 return new UnicodeEscaper() { 125 @Override 126 protected char[] escape(int cp) { 127 return replacementMap.get(cp); 128 } 129 }; 130 } 131 } 132