001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.text; 017 018import static org.hamcrest.core.Is.is; 019import static org.hamcrest.core.IsNull.notNullValue; 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertThat; 022import org.junit.Test; 023 024/** 025 * Unit test for {@link XmlNameEncoder} 026 * 027 * @author Randall Hauch 028 * @author Horia Chiorean 029 */ 030public class XmlNameEncoderTest { 031 032 private XmlNameEncoder encoder = new XmlNameEncoder(); 033 034 protected void checkEncoding( String input, 035 String expected ) { 036 String output = this.encoder.encode(input); 037 assertThat(output, is(notNullValue())); 038 assertEquals(expected, output); 039 assertThat(output.length(), is(expected.length())); 040 assertThat(output, is(expected)); 041 042 checkDecoding(output, input); 043 } 044 045 protected void checkForNoEncoding( String input ) { 046 String output = this.encoder.encode(input); 047 assertThat(output, is(notNullValue())); 048 assertEquals(input, output); 049 assertThat(output.length(), is(input.length())); 050 assertThat(output, is(input)); 051 052 checkForNoDecoding(input); 053 } 054 055 protected void checkForNoDecoding( String input ) { 056 String output = this.encoder.decode(input); 057 assertThat(output, is(notNullValue())); 058 assertEquals(input, output); 059 assertThat(output.length(), is(input.length())); 060 assertThat(output, is(input)); 061 } 062 063 protected void checkDecoding( String input, 064 String output ) { 065 String decoded = this.encoder.decode(input); 066 assertEquals(output, decoded); 067 assertThat(decoded.length(), is(output.length())); 068 assertThat(decoded, is(output)); 069 } 070 071 @Test 072 public void shouldNotEncodeUnderscoreIfNotFollowedByLowercaseX() { 073 checkForNoEncoding("Employee_ID"); 074 checkForNoEncoding("_Employee_"); 075 checkForNoEncoding("Employee__ID"); 076 } 077 078 @Test 079 public void shouldEncodeUnderscoreIfFollowedByLowercaseX() { 080 checkEncoding("Employee_x", "Employee_x005f_x"); 081 checkEncoding("Employee_x0", "Employee_x005f_x0"); 082 checkEncoding("Employee_x0022_", "Employee_x005f_x0022_"); 083 } 084 085 @Test 086 public void shouldNotDecodeIfNotValidHexadecimalValue() { 087 checkForNoDecoding("_xH013_"); 088 } 089 090 @Test 091 public void shouldNotDecodeIfNotValidEncodedFormat() { 092 checkForNoDecoding("_X0022_"); // No lowercase 'x' 093 checkForNoDecoding("x0022_"); // No leading '_' 094 checkForNoDecoding("_x0022a"); // No trailing '_' 095 } 096 097 @Test 098 public void shouldNotEncodeDigits() { 099 for (char c = '\u0030'; c <= '\u0039'; c++) { // digit 100 checkForNoEncoding("Employee" + c + "xyz"); 101 } 102 } 103 104 @Test 105 public void shouldNotEncodeAlphabeticCharacters() { 106 for (char c = '\u0041'; c <= '\u005a'; c++) { // digit 107 checkForNoEncoding("Employee" + c + "xyz"); 108 } 109 for (char c = '\u0061'; c <= '\u007a'; c++) { // digit 110 checkForNoEncoding("Employee" + c + "xyz"); 111 } 112 } 113 114 @Test 115 public void shouldNotEncodePeriodOrDashOrUnderscoreCharacters() { 116 checkForNoEncoding("Employee.xyz"); 117 checkForNoEncoding("Employee-xyz"); 118 checkForNoEncoding("Employee:xyz"); 119 checkForNoEncoding("Employee_abc"); 120 } 121 122 @Test 123 public void shouldDecodeIfCompleteHexadecimal() { 124 checkDecoding("Employee_", "Employee_"); 125 checkDecoding("Employee_x", "Employee_x"); 126 checkDecoding("Employee_x0", "Employee_x0"); 127 checkDecoding("Employee_x00", "Employee_x00"); 128 checkDecoding("Employee_x002", "Employee_x002"); 129 checkDecoding("Employee_x0022", "Employee_x0022"); 130 checkDecoding("_", "_"); 131 checkDecoding("_x", "_x"); 132 checkDecoding("_x0", "_x0"); 133 checkDecoding("_x00", "_x00"); 134 checkDecoding("_x002", "_x002"); 135 checkDecoding("_x0022", "_x0022"); 136 } 137 138 @Test 139 public void shouldEncodeUnderscoreOnlyWhenFollowedByX() { 140 checkEncoding("Employee_xyz", "Employee_x005f_xyz"); 141 checkEncoding("Employee_ayz", "Employee_ayz"); 142 } 143 144 @Test 145 public void shouldEncodeNonAlphaNumericCharacters() { 146 checkEncoding("Employee!xyz", "Employee_x0021_xyz"); 147 checkEncoding("Employee\"xyz", "Employee_x0022_xyz"); 148 checkEncoding("Employee#xyz", "Employee_x0023_xyz"); 149 checkEncoding("Employee$xyz", "Employee_x0024_xyz"); 150 checkEncoding("Employee%xyz", "Employee_x0025_xyz"); 151 checkEncoding("Employee&xyz", "Employee_x0026_xyz"); 152 checkEncoding("Employee'xyz", "Employee_x0027_xyz"); 153 checkEncoding("Employee(xyz", "Employee_x0028_xyz"); 154 checkEncoding("Employee)xyz", "Employee_x0029_xyz"); 155 checkEncoding("Employee*xyz", "Employee_x002a_xyz"); 156 checkEncoding("Employee+xyz", "Employee_x002b_xyz"); 157 checkEncoding("Employee,xyz", "Employee_x002c_xyz"); 158 checkEncoding("Employee/xyz", "Employee_x002f_xyz"); 159 checkEncoding("Employee\u0B9Bxyz", "Employee_x0b9b_xyz"); 160 } 161 162 @Test 163 public void shouldEncodeIllegalStartCharacter() { 164 checkEncoding("042b4500-a8bc-4b79-8af0-59fb408ecfa5", "_x0030_42b4500-a8bc-4b79-8af0-59fb408ecfa5"); 165 checkEncoding("-42b4500-a8bc-4b79-8af0-59fb408ecfa5", "_x002d_42b4500-a8bc-4b79-8af0-59fb408ecfa5"); 166 checkEncoding(".42b4500-a8bc-4b79-8af0-59fb408ecfa5", "_x002e_42b4500-a8bc-4b79-8af0-59fb408ecfa5"); 167 } 168 169 @Test 170 public void shouldDecodeIllegalStartCharacter() { 171 checkDecoding("_x0030_42b4500-a8bc-4b79-8af0-59fb408ecfa5", "042b4500-a8bc-4b79-8af0-59fb408ecfa5"); 172 checkDecoding("_x002d_42b4500-a8bc-4b79-8af0-59fb408ecfa5", "-42b4500-a8bc-4b79-8af0-59fb408ecfa5"); 173 checkDecoding("_x002e_42b4500-a8bc-4b79-8af0-59fb408ecfa5", ".42b4500-a8bc-4b79-8af0-59fb408ecfa5"); 174 } 175 176}