1 /* 2 * Copyright (C) 2007 The Android Open Source Project 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 android.content; 18 19 import android.net.Uri; 20 21 import androidx.test.filters.SmallTest; 22 23 import junit.framework.TestCase; 24 25 import java.lang.reflect.Field; 26 import java.util.ArrayList; 27 28 public class UriMatcherTest extends TestCase { 29 30 static final int ROOT = 0; 31 static final int PEOPLE = 1; 32 static final int PEOPLE_ID = 2; 33 static final int PEOPLE_PHONES = 3; 34 static final int PEOPLE_PHONES_ID = 4; 35 static final int PEOPLE_ADDRESSES = 5; 36 static final int PEOPLE_ADDRESSES_ID = 6; 37 static final int PEOPLE_CONTACTMETH = 7; 38 static final int PEOPLE_CONTACTMETH_ID = 8; 39 static final int CALLS = 9; 40 static final int CALLS_ID = 10; 41 static final int CALLERID = 11; 42 static final int CALLERID_TEXT = 12; 43 static final int FILTERRECENT = 13; 44 static final int ANOTHER_PATH_SEGMENT = 13; 45 46 @SmallTest testContentUris()47 public void testContentUris() { 48 UriMatcher matcher = new UriMatcher(ROOT); 49 matcher.addURI("people", null, PEOPLE); 50 matcher.addURI("people", "#", PEOPLE_ID); 51 matcher.addURI("people", "#/phones", PEOPLE_PHONES); 52 matcher.addURI("people", "#/phones/blah", PEOPLE_PHONES_ID); 53 matcher.addURI("people", "#/phones/#", PEOPLE_PHONES_ID); 54 matcher.addURI("people", "#/addresses", PEOPLE_ADDRESSES); 55 matcher.addURI("people", "#/addresses/#", PEOPLE_ADDRESSES_ID); 56 matcher.addURI("people", "#/contact-methods", PEOPLE_CONTACTMETH); 57 matcher.addURI("people", "#/contact-methods/#", PEOPLE_CONTACTMETH_ID); 58 matcher.addURI("calls", null, CALLS); 59 matcher.addURI("calls", "#", CALLS_ID); 60 matcher.addURI("caller-id", null, CALLERID); 61 matcher.addURI("caller-id", "*", CALLERID_TEXT); 62 matcher.addURI("filter-recent", null, FILTERRECENT); 63 matcher.addURI("auth", "another/path/segment", ANOTHER_PATH_SEGMENT); 64 checkAll(matcher); 65 } 66 67 @SmallTest testContentUrisWithLeadingSlash()68 public void testContentUrisWithLeadingSlash() { 69 UriMatcher matcher = new UriMatcher(ROOT); 70 matcher.addURI("people", null, PEOPLE); 71 matcher.addURI("people", "/#", PEOPLE_ID); 72 matcher.addURI("people", "/#/phones", PEOPLE_PHONES); 73 matcher.addURI("people", "/#/phones/blah", PEOPLE_PHONES_ID); 74 matcher.addURI("people", "/#/phones/#", PEOPLE_PHONES_ID); 75 matcher.addURI("people", "/#/addresses", PEOPLE_ADDRESSES); 76 matcher.addURI("people", "/#/addresses/#", PEOPLE_ADDRESSES_ID); 77 matcher.addURI("people", "/#/contact-methods", PEOPLE_CONTACTMETH); 78 matcher.addURI("people", "/#/contact-methods/#", PEOPLE_CONTACTMETH_ID); 79 matcher.addURI("calls", null, CALLS); 80 matcher.addURI("calls", "/#", CALLS_ID); 81 matcher.addURI("caller-id", null, CALLERID); 82 matcher.addURI("caller-id", "/*", CALLERID_TEXT); 83 matcher.addURI("filter-recent", null, FILTERRECENT); 84 matcher.addURI("auth", "/another/path/segment", ANOTHER_PATH_SEGMENT); 85 checkAll(matcher); 86 } 87 88 @SmallTest testContentUrisWithLeadingSlashAndOnlySlash()89 public void testContentUrisWithLeadingSlashAndOnlySlash() { 90 UriMatcher matcher = new UriMatcher(ROOT); 91 matcher.addURI("people", "/", PEOPLE); 92 matcher.addURI("people", "/#", PEOPLE_ID); 93 matcher.addURI("people", "/#/phones", PEOPLE_PHONES); 94 matcher.addURI("people", "/#/phones/blah", PEOPLE_PHONES_ID); 95 matcher.addURI("people", "/#/phones/#", PEOPLE_PHONES_ID); 96 matcher.addURI("people", "/#/addresses", PEOPLE_ADDRESSES); 97 matcher.addURI("people", "/#/addresses/#", PEOPLE_ADDRESSES_ID); 98 matcher.addURI("people", "/#/contact-methods", PEOPLE_CONTACTMETH); 99 matcher.addURI("people", "/#/contact-methods/#", PEOPLE_CONTACTMETH_ID); 100 matcher.addURI("calls", "/", CALLS); 101 matcher.addURI("calls", "/#", CALLS_ID); 102 matcher.addURI("caller-id", "/", CALLERID); 103 matcher.addURI("caller-id", "/*", CALLERID_TEXT); 104 matcher.addURI("filter-recent", null, FILTERRECENT); 105 matcher.addURI("auth", "/another/path/segment", ANOTHER_PATH_SEGMENT); 106 checkAll(matcher); 107 } 108 109 /** 110 * Tests that different {@link UriMatcher}s for {@code "#"} use the same 111 * instance of the String {@code "#"}. 112 */ 113 @SmallTest testTextCreatesNoDuplicateStrings()114 public void testTextCreatesNoDuplicateStrings() throws Exception { 115 // Change the visibility of fields so that they can be tested without 116 // making it non-private. 117 Field textField = UriMatcher.class.getDeclaredField("mText"); 118 textField.setAccessible(true); 119 120 UriMatcher matcher = new UriMatcher(ROOT); 121 matcher.addURI("authority", "people/#", PEOPLE_ID); 122 matcher.addURI("authority", "calls/#", CALLS_ID); 123 124 UriMatcher authorityChild = getOnlyChild(matcher); 125 ArrayList<UriMatcher> mChildren = getChildren(authorityChild); 126 UriMatcher peopleChild = mChildren.get(0); 127 UriMatcher callsChild = mChildren.get(1); 128 assertEquals("people", textField.get(peopleChild)); 129 assertEquals("calls", textField.get(callsChild)); 130 UriMatcher peopleSharp = getOnlyChild(peopleChild); 131 UriMatcher callsSharp = getOnlyChild(callsChild); 132 assertTrue("There should be only one instance of String `#` but `" 133 + textField.get(peopleSharp) + "` is not `" 134 + textField.get(callsSharp) + "`", 135 textField.get(peopleSharp) == textField.get(callsSharp)); 136 } 137 138 /** 139 * Returns {@link UriMatcher#mChildren}. 140 */ getChildren(UriMatcher matcher)141 private ArrayList<UriMatcher> getChildren(UriMatcher matcher) 142 throws IllegalAccessException, NoSuchFieldException { 143 // Change the visibility of fields so that they can be tested without 144 // making it non-private. 145 Field childrenField = UriMatcher.class.getDeclaredField("mChildren"); 146 childrenField.setAccessible(true); 147 return (ArrayList<UriMatcher>) childrenField.get(matcher); 148 149 } 150 151 /** 152 * Returns the only element of {@link UriMatcher#mChildren}. 153 */ getOnlyChild(UriMatcher matcher)154 private UriMatcher getOnlyChild(UriMatcher matcher) 155 throws IllegalAccessException, NoSuchFieldException { 156 ArrayList<UriMatcher> children = getChildren(matcher); 157 assertEquals("There should be one child for " + matcher, 158 1, children.size()); 159 return children.get(0); 160 } 161 checkAll(UriMatcher matcher)162 private void checkAll(UriMatcher matcher) { 163 check("content://asdf", UriMatcher.NO_MATCH, matcher); 164 check("content://people", PEOPLE, matcher); 165 check("content://people/", PEOPLE, matcher); 166 check("content://people/1", PEOPLE_ID, matcher); 167 check("content://people/asdf", UriMatcher.NO_MATCH, matcher); 168 check("content://people/2/phones", PEOPLE_PHONES, matcher); 169 check("content://people/2/phones/3", PEOPLE_PHONES_ID, matcher); 170 check("content://people/2/phones/asdf", UriMatcher.NO_MATCH, matcher); 171 check("content://people/2/addresses", PEOPLE_ADDRESSES, matcher); 172 check("content://people/2/addresses/3", PEOPLE_ADDRESSES_ID, matcher); 173 check("content://people/2/addresses/asdf", UriMatcher.NO_MATCH, matcher); 174 check("content://people/2/contact-methods", PEOPLE_CONTACTMETH, matcher); 175 check("content://people/2/contact-methods/3", PEOPLE_CONTACTMETH_ID, matcher); 176 check("content://people/2/contact-methods/asdf", UriMatcher.NO_MATCH, matcher); 177 check("content://calls", CALLS, matcher); 178 check("content://calls/", CALLS, matcher); 179 check("content://calls/1", CALLS_ID, matcher); 180 check("content://calls/asdf", UriMatcher.NO_MATCH, matcher); 181 check("content://caller-id", CALLERID, matcher); 182 check("content://caller-id/", CALLERID, matcher); 183 check("content://caller-id/asdf", CALLERID_TEXT, matcher); 184 check("content://caller-id/1", CALLERID_TEXT, matcher); 185 check("content://filter-recent", FILTERRECENT, matcher); 186 check("content://auth/another/path/segment", ANOTHER_PATH_SEGMENT, matcher); 187 } 188 check(String uri, int expected, UriMatcher matcher)189 private void check(String uri, int expected, UriMatcher matcher) { 190 int result = matcher.match(Uri.parse(uri)); 191 if (result != expected) { 192 String msg = "failed on " + uri; 193 msg += " expected " + expected + " got " + result; 194 throw new RuntimeException(msg); 195 } 196 } 197 } 198 199