Skip to content

Commit

Permalink
GEODE-8288: Match Native Redis's glob-style pattern (apache#5282)
Browse files Browse the repository at this point in the history
  • Loading branch information
sabbey37 authored Jun 24, 2020
1 parent 210dc4f commit 5256fde
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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
*
* http://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.apache.geode.redis.internal.executor;

import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.rules.TestRule;
import org.testcontainers.containers.GenericContainer;
import redis.clients.jedis.Jedis;

import org.apache.geode.test.junit.rules.IgnoreOnWindowsRule;

public class GlobPatternNativeRedisAcceptanceTest extends GlobPatternIntegrationTest {

// Docker compose does not work on windows in CI. Ignore this test on windows
// Using a RuleChain to make sure we ignore the test before the rule comes into play
@ClassRule
public static TestRule ignoreOnWindowsRule = new IgnoreOnWindowsRule();

@BeforeClass
public static void setUp() {
GenericContainer redisContainer = new GenericContainer<>("redis:5.0.6").withExposedPorts(6379);
redisContainer.start();
jedis = new Jedis("localhost", redisContainer.getFirstMappedPort(), REDIS_CLIENT_TIMEOUT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package org.apache.geode.redis.internal.executor.key;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.experimental.categories.Category;
Expand All @@ -41,9 +40,4 @@ public static void setUp() {
jedis = new Jedis("localhost", redisContainer.getFirstMappedPort(), REDIS_CLIENT_TIMEOUT);
}

@AfterClass
public static void tearDown() {
jedis.close();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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
*
* http://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.apache.geode.redis.internal.executor;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import redis.clients.jedis.Jedis;

import org.apache.geode.redis.GeodeRedisServerRule;
import org.apache.geode.test.awaitility.GeodeAwaitility;

public class GlobPatternIntegrationTest {

public static Jedis jedis;
public static int REDIS_CLIENT_TIMEOUT =
Math.toIntExact(GeodeAwaitility.getTimeout().toMillis());

@ClassRule
public static GeodeRedisServerRule server = new GeodeRedisServerRule();

@BeforeClass
public static void setUp() {
jedis = new Jedis("localhost", server.getPort(), REDIS_CLIENT_TIMEOUT);
}

@After
public void flushAll() {
jedis.flushAll();
}

@AfterClass
public static void tearDown() {
jedis.close();
}

@Test
public void asterisk_matchesAnySequenceOfCharacters() {
jedis.set("ble", "value");
jedis.set("blo9%^e", "value");
jedis.set("blooo", "value");

assertThat(jedis.keys("bl*e")).containsExactlyInAnyOrder("ble", "blo9%^e");
}

@Test
public void questionMark_matchesAnySingleCharacter() {
jedis.set("hollo", "value");
jedis.set("hello", "value");
jedis.set("hoollo", "value");

assertThat(jedis.keys("h?llo")).containsExactlyInAnyOrder("hollo", "hello");
}

@Test
public void charactersInsideBrackets_matchSpecifiedCharacters() {
jedis.set("top", "value");
jedis.set("tap", "value");
jedis.set("tep", "value");

assertThat(jedis.keys("t[oa]p")).containsExactlyInAnyOrder("top", "tap");
}

@Test
public void dashInsideBrackets_matchesSpecifiedRangeOfCharacters() {
jedis.set("smch", "value");
jedis.set("srch", "value");
jedis.set("such", "value");

assertThat(jedis.keys("s[m-s]ch")).containsExactlyInAnyOrder("smch", "srch");
}

@Test
public void caretInsideBrackets_doesNotMatchSpecifiedCharacter() {
jedis.set("patches", "value");
jedis.set("petches", "value");
jedis.set("potches", "value");

assertThat(jedis.keys("p[^o]tches")).containsExactlyInAnyOrder("petches", "patches");
}

@Test
public void charactersInsideUnclosedBracket_matchSpecifiedCharacters() {
jedis.set("*", "value");
jedis.set("}", "value");
jedis.set("4", "value");
jedis.set("[", "value");

assertThat(jedis.keys("[*}4")).containsExactlyInAnyOrder("*", "}", "4");
}

@Test
public void dashInsideUnclosedBracket_matchesSpecifiedRangeOfCharacters() {
jedis.set("sm", "value");
jedis.set("ss", "value");
jedis.set("ssch", "value");

assertThat(jedis.keys("s[m-sch")).containsExactlyInAnyOrder("sm", "ss");
}

@Test
public void caretInsideUnclosedBracket_doesNotMatchSpecifiedCharacter() {
jedis.set("kermi", "value");
jedis.set("kermu", "value");
jedis.set("kermo", "value");

assertThat(jedis.keys("kerm[^i")).containsExactlyInAnyOrder("kermu", "kermo");
}

@Test
public void doubleOpenBracket_matchesSpecifiedCharacters() {
jedis.set("*", "value");
jedis.set("[", "value");
jedis.set("[4", "value");
jedis.set("&8t", "value");

assertThat(jedis.keys("[[*")).containsExactlyInAnyOrder("*", "[");
}

@Test
public void escapedOpenBracket_matchesVerbatim() {
jedis.set("[", "value");
jedis.set("[o9$", "value");
jedis.set("such", "value");

assertThat(jedis.keys("\\[*")).containsExactlyInAnyOrder("[", "[o9$");
}

@Test
public void escapedQuestionMark_matchesVerbatim() {
jedis.set("?", "value");
jedis.set("?oo", "value");
jedis.set("such", "value");

assertThat(jedis.keys("\\?*")).containsExactlyInAnyOrder("?", "?oo");
}

@Test
public void escapedAsterisk_matchesVerbatim() {
jedis.set("*", "value");
jedis.set("*9x", "value");
jedis.set("such", "value");

assertThat(jedis.keys("\\**")).containsExactlyInAnyOrder("*", "*9x");
}

@Test
public void caretOutsideBrackets_matchesVerbatim() {
jedis.set("^o", "value");
jedis.set("^o99", "value");
jedis.set("^O", "value");

assertThat(jedis.keys("^o*")).containsExactlyInAnyOrder("^o", "^o99");
}

@Test
public void openCurly_matchesVerbatim() {
jedis.set("{", "value");
jedis.set("{&0", "value");
jedis.set("bogus", "value");

assertThat(jedis.keys("{*")).containsExactlyInAnyOrder("{", "{&0");
}

@Test
public void closedCurly_matchesVerbatim() {
jedis.set("}", "value");
jedis.set("}&0", "value");
jedis.set("bogus", "value");

assertThat(jedis.keys("}*")).containsExactlyInAnyOrder("}", "}&0");
}

@Test
public void comma_matchesVerbatim() {
jedis.set("kermit", "value");
jedis.set("kerm,t", "value");
jedis.set("kermot", "value");
jedis.set("kermat", "value");

assertThat(jedis.keys("kerm[i,o]t")).containsExactlyInAnyOrder("kermit", "kermot", "kerm,t");
}

@Test
public void exclamationPoint_matchesVerbatim() {
jedis.set("kerm!t", "value");
jedis.set("kermot", "value");
jedis.set("kermit", "value");

assertThat(jedis.keys("kerm[!i]t")).containsExactlyInAnyOrder("kermit", "kerm!t");
}

@Test
public void period_matchesVerbatim() {
jedis.set("...", "value");
jedis.set(".", "value");
jedis.set(".&*", "value");
jedis.set("kermat", "value");

assertThat(jedis.keys(".*")).containsExactlyInAnyOrder("...", ".", ".&*");
}

@Test
public void plusSign_matchesVerbatim() {
jedis.set("ab", "value");
jedis.set("aaaaab", "value");
jedis.set("a+b", "value");

assertThat(jedis.keys("a+b")).containsExactlyInAnyOrder("a+b");
}

@Test
public void orSign_matchesVerbatim() {
jedis.set("cat|dog", "value");
jedis.set("cat", "value");
jedis.set("dog", "value");

assertThat(jedis.keys("cat|dog")).containsExactlyInAnyOrder("cat|dog");
}

@Test
public void dollarSign_matchesVerbatim() {
jedis.set("the cat", "value");
jedis.set("the cat$", "value");
jedis.set("dog", "value");

assertThat(jedis.keys("the cat$")).containsExactlyInAnyOrder("the cat$");
}

@Test
public void parentheses_matchVerbatim() {
jedis.set("orange(cat)z", "value");
jedis.set("orange", "value");
jedis.set("orangecat", "value");

assertThat(jedis.keys("orange(cat)?")).containsExactlyInAnyOrder("orange(cat)z");
}

@Test
public void escapedBackslash_matchesVerbatim() {
jedis.set("\\", "value");
jedis.set("\\!", "value");
jedis.set("*", "value");

assertThat(jedis.keys("\\\\*")).containsExactlyInAnyOrder("\\", "\\!");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static void tearDown() {
}

@Test
public void keys_givenSplat_withASCIIdata_returnsExpectedMatches() {
public void givenSplat_withASCIIdata_returnsExpectedMatches() {
jedis.set("string1", "v1");
jedis.sadd("set1", "member1");
jedis.hset("hash1", "key1", "field1");
Expand All @@ -63,7 +63,7 @@ public void keys_givenSplat_withASCIIdata_returnsExpectedMatches() {
}

@Test
public void keys_givenSplat_withBinaryData_returnsExpectedMatches() {
public void givenSplat_withBinaryData_returnsExpectedMatches() {
byte[] stringKey =
new byte[] {(byte) 0xac, (byte) 0xed, 0, 4, 0, 5, 's', 't', 'r', 'i', 'n', 'g', '1'};
byte[] value = new byte[] {'v', '1'};
Expand All @@ -86,11 +86,15 @@ public void keys_givenSplat_withBinaryData_returnsExpectedMatches() {
}

@Test
public void keys_givenBinaryValue_withExactMatch_preservesBinaryData() {
public void givenBinaryValue_withExactMatch_preservesBinaryData() {
byte[] stringKey =
new byte[] {(byte) 0xac, (byte) 0xed, 0, 4, 0, 5, 's', 't', 'r', 'i', 'n', 'g', '1'};
jedis.set(stringKey, stringKey);
assertThat(jedis.keys(stringKey)).containsExactlyInAnyOrder(stringKey);
}

@Test
public void givenMalformedGlobPattern_returnsEmptySet() {
assertThat(jedis.keys("[][]")).isEmpty();
}
}
Loading

0 comments on commit 5256fde

Please sign in to comment.