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 23 import junit.framework.TestCase; 24 25 import java.io.IOException; 26 27 /** 28 * @author David Beaumont 29 */ 30 @GwtCompatible 31 public class EscapersTest extends TestCase { testNullEscaper()32 public void testNullEscaper() throws IOException { 33 Escaper escaper = Escapers.nullEscaper(); 34 EscaperAsserts.assertBasic(escaper); 35 String s = "\0\n\t\\az09~\uD800\uDC00\uFFFF"; 36 assertEquals("null escaper should have no effect", s, escaper.escape(s)); 37 } 38 testBuilderInitialStateNoReplacement()39 public void testBuilderInitialStateNoReplacement() { 40 // Unsafe characters aren't modified by default (unsafeReplacement == null). 41 Escaper escaper = Escapers.builder().setSafeRange('a', 'z').build(); 42 assertEquals("The Quick Brown Fox", escaper.escape("The Quick Brown Fox")); 43 } 44 testBuilderInitialStateNoneUnsafe()45 public void testBuilderInitialStateNoneUnsafe() { 46 // No characters are unsafe by default (safeMin == 0, safeMax == 0xFFFF). 47 Escaper escaper = Escapers.builder().setUnsafeReplacement("X").build(); 48 assertEquals("\0\uFFFF", escaper.escape("\0\uFFFF")); 49 } 50 testBuilderRetainsState()51 public void testBuilderRetainsState() { 52 // Setting a safe range and unsafe replacement works as expected. 53 Escapers.Builder builder = Escapers.builder(); 54 builder.setSafeRange('a', 'z'); 55 builder.setUnsafeReplacement("X"); 56 assertEquals("XheXXuickXXrownXXoxX", 57 builder.build().escape("The Quick Brown Fox!")); 58 // Explicit replacements take priority over unsafe characters. 59 builder.addEscape(' ', "_"); 60 builder.addEscape('!', "_"); 61 assertEquals("Xhe_Xuick_Xrown_Xox_", 62 builder.build().escape("The Quick Brown Fox!")); 63 // Explicit replacements take priority over safe characters. 64 builder.setSafeRange(' ', '~'); 65 assertEquals("The_Quick_Brown_Fox_", 66 builder.build().escape("The Quick Brown Fox!")); 67 } 68 testBuilderCreatesIndependentEscapers()69 public void testBuilderCreatesIndependentEscapers() { 70 // Setup a simple builder and create the first escaper. 71 Escapers.Builder builder = Escapers.builder(); 72 builder.setSafeRange('a', 'z'); 73 builder.setUnsafeReplacement("X"); 74 builder.addEscape(' ', "_"); 75 Escaper first = builder.build(); 76 // Modify one of the existing mappings before creating a new escaper. 77 builder.addEscape(' ', "-"); 78 builder.addEscape('!', "$"); 79 Escaper second = builder.build(); 80 // This should have no effect on existing escapers. 81 builder.addEscape(' ', "*"); 82 83 // Test both escapers after modifying the builder. 84 assertEquals("Xhe_Xuick_Xrown_XoxX", first.escape("The Quick Brown Fox!")); 85 assertEquals("Xhe-Xuick-Xrown-Xox$", second.escape("The Quick Brown Fox!")); 86 } 87 testAsUnicodeEscaper()88 public void testAsUnicodeEscaper() throws IOException { 89 CharEscaper charEscaper = createSimpleCharEscaper( 90 ImmutableMap.<Character, char[]>builder() 91 .put('x', "<hello>".toCharArray()) 92 .put('\uD800', "<hi>".toCharArray()) 93 .put('\uDC00', "<lo>".toCharArray()) 94 .build()); 95 UnicodeEscaper unicodeEscaper = Escapers.asUnicodeEscaper(charEscaper); 96 EscaperAsserts.assertBasic(unicodeEscaper); 97 assertEquals("<hello><hi><lo>", charEscaper.escape("x\uD800\uDC00")); 98 assertEquals("<hello><hi><lo>", unicodeEscaper.escape("x\uD800\uDC00")); 99 100 // Test that wrapped escapers acquire good Unicode semantics. 101 assertEquals("<hi><hello><lo>", charEscaper.escape("\uD800x\uDC00")); 102 try { 103 unicodeEscaper.escape("\uD800x\uDC00"); 104 fail("should have failed for bad Unicode input"); 105 } catch (IllegalArgumentException e) { 106 // pass 107 } 108 assertEquals("<lo><hi>", charEscaper.escape("\uDC00\uD800")); 109 try { 110 unicodeEscaper.escape("\uDC00\uD800"); 111 fail("should have failed for bad Unicode input"); 112 } catch (IllegalArgumentException e) { 113 // pass 114 } 115 } 116 117 // A trival non-optimized escaper for testing. createSimpleCharEscaper( final ImmutableMap<Character, char[]> replacementMap)118 private CharEscaper createSimpleCharEscaper( 119 final ImmutableMap<Character, char[]> replacementMap) { 120 return new CharEscaper() { 121 @Override protected char[] escape(char c) { 122 return replacementMap.get(c); 123 } 124 }; 125 } 126 127 // A trival non-optimized escaper for testing. 128 private UnicodeEscaper createSimpleUnicodeEscaper( 129 final ImmutableMap<Integer, char[]> replacementMap) { 130 return new UnicodeEscaper() { 131 @Override protected char[] escape(int cp) { 132 return replacementMap.get(cp); 133 } 134 }; 135 } 136 } 137