001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.replication;
019
020import static org.junit.Assert.assertNull;
021import static org.junit.Assert.assertTrue;
022import static org.mockito.Mockito.mock;
023import static org.mockito.Mockito.when;
024
025import java.util.ArrayList;
026import java.util.HashMap;
027import java.util.HashSet;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031import java.util.TreeMap;
032import org.apache.hadoop.hbase.Cell;
033import org.apache.hadoop.hbase.CellComparatorImpl;
034import org.apache.hadoop.hbase.HBaseClassTestRule;
035import org.apache.hadoop.hbase.HConstants;
036import org.apache.hadoop.hbase.KeyValue;
037import org.apache.hadoop.hbase.TableName;
038import org.apache.hadoop.hbase.client.RegionInfoBuilder;
039import org.apache.hadoop.hbase.security.access.PermissionStorage;
040import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
041import org.apache.hadoop.hbase.testclassification.ReplicationTests;
042import org.apache.hadoop.hbase.testclassification.SmallTests;
043import org.apache.hadoop.hbase.util.Bytes;
044import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
045import org.apache.hadoop.hbase.wal.WAL.Entry;
046import org.apache.hadoop.hbase.wal.WALEdit;
047import org.apache.hadoop.hbase.wal.WALEditInternalHelper;
048import org.apache.hadoop.hbase.wal.WALKeyImpl;
049import org.junit.Assert;
050import org.junit.ClassRule;
051import org.junit.Test;
052import org.junit.experimental.categories.Category;
053
054import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
055
056@Category({ ReplicationTests.class, SmallTests.class })
057public class TestReplicationWALEntryFilters {
058
059  @ClassRule
060  public static final HBaseClassTestRule CLASS_RULE =
061    HBaseClassTestRule.forClass(TestReplicationWALEntryFilters.class);
062
063  static byte[] a = new byte[] { 'a' };
064  static byte[] b = new byte[] { 'b' };
065  static byte[] c = new byte[] { 'c' };
066  static byte[] d = new byte[] { 'd' };
067
068  @Test
069  public void testSystemTableWALEntryFilter() {
070    SystemTableWALEntryFilter filter = new SystemTableWALEntryFilter();
071
072    // meta
073    WALKeyImpl key1 =
074      new WALKeyImpl(RegionInfoBuilder.FIRST_META_REGIONINFO.getEncodedNameAsBytes(),
075        TableName.META_TABLE_NAME, EnvironmentEdgeManager.currentTime());
076    Entry metaEntry = new Entry(key1, null);
077
078    assertNull(filter.filter(metaEntry));
079
080    // user table
081    WALKeyImpl key3 =
082      new WALKeyImpl(new byte[0], TableName.valueOf("foo"), EnvironmentEdgeManager.currentTime());
083    Entry userEntry = new Entry(key3, null);
084
085    assertEquals(userEntry, filter.filter(userEntry));
086
087    // hbase:acl should be allowed through the filter
088    WALKeyImpl key4 =
089      new WALKeyImpl(new byte[0], PermissionStorage.ACL_TABLE_NAME, System.currentTimeMillis());
090    Entry aclEntry = new Entry(key4, null);
091    assertEquals(aclEntry, filter.filter(aclEntry));
092
093    // hbase:labels should be allowed through the filter
094    WALKeyImpl key5 = new WALKeyImpl(new byte[0], VisibilityConstants.LABELS_TABLE_NAME,
095      System.currentTimeMillis());
096    Entry labelsEntry = new Entry(key5, null);
097    assertEquals(labelsEntry, filter.filter(labelsEntry));
098  }
099
100  @Test
101  public void testScopeWALEntryFilter() {
102    WALEntryFilter filter = new ChainWALEntryFilter(new ScopeWALEntryFilter());
103
104    Entry userEntry = createEntry(null, a, b);
105    Entry userEntryA = createEntry(null, a);
106    Entry userEntryB = createEntry(null, b);
107    Entry userEntryEmpty = createEntry(null);
108
109    // no scopes
110    // now we will not filter out entries without a replication scope since serial replication still
111    // need the sequence id, but the cells will all be filtered out.
112    assertTrue(filter.filter(userEntry).getEdit().isEmpty());
113
114    // empty scopes
115    // ditto
116    TreeMap<byte[], Integer> scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
117    userEntry = createEntry(scopes, a, b);
118    assertTrue(filter.filter(userEntry).getEdit().isEmpty());
119
120    // different scope
121    scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
122    scopes.put(c, HConstants.REPLICATION_SCOPE_GLOBAL);
123    userEntry = createEntry(scopes, a, b);
124    // all kvs should be filtered
125    assertEquals(userEntryEmpty, filter.filter(userEntry));
126
127    // local scope
128    scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
129    scopes.put(a, HConstants.REPLICATION_SCOPE_LOCAL);
130    userEntry = createEntry(scopes, a, b);
131    assertEquals(userEntryEmpty, filter.filter(userEntry));
132    scopes.put(b, HConstants.REPLICATION_SCOPE_LOCAL);
133    assertEquals(userEntryEmpty, filter.filter(userEntry));
134
135    // only scope a
136    scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
137    scopes.put(a, HConstants.REPLICATION_SCOPE_GLOBAL);
138    userEntry = createEntry(scopes, a, b);
139    assertEquals(userEntryA, filter.filter(userEntry));
140    scopes.put(b, HConstants.REPLICATION_SCOPE_LOCAL);
141    assertEquals(userEntryA, filter.filter(userEntry));
142
143    // only scope b
144    scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
145    scopes.put(b, HConstants.REPLICATION_SCOPE_GLOBAL);
146    userEntry = createEntry(scopes, a, b);
147    assertEquals(userEntryB, filter.filter(userEntry));
148    scopes.put(a, HConstants.REPLICATION_SCOPE_LOCAL);
149    assertEquals(userEntryB, filter.filter(userEntry));
150
151    // scope a and b
152    scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
153    scopes.put(b, HConstants.REPLICATION_SCOPE_GLOBAL);
154    userEntry = createEntry(scopes, a, b);
155    assertEquals(userEntryB, filter.filter(userEntry));
156    scopes.put(a, HConstants.REPLICATION_SCOPE_LOCAL);
157    assertEquals(userEntryB, filter.filter(userEntry));
158  }
159
160  WALEntryFilter nullFilter = new WALEntryFilter() {
161    @Override
162    public Entry filter(Entry entry) {
163      return null;
164    }
165  };
166
167  WALEntryFilter passFilter = new WALEntryFilter() {
168    @Override
169    public Entry filter(Entry entry) {
170      return entry;
171    }
172  };
173
174  public static class FilterSomeCellsWALCellFilter implements WALEntryFilter, WALCellFilter {
175    @Override
176    public Entry filter(Entry entry) {
177      return entry;
178    }
179
180    @Override
181    public Cell filterCell(Entry entry, Cell cell) {
182      if (
183        Bytes.toString(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()).equals("a")
184      ) {
185        return null;
186      } else {
187        return cell;
188      }
189    }
190  }
191
192  public static class FilterAllCellsWALCellFilter implements WALEntryFilter, WALCellFilter {
193    @Override
194    public Entry filter(Entry entry) {
195      return entry;
196    }
197
198    @Override
199    public Cell filterCell(Entry entry, Cell cell) {
200      return null;
201    }
202  }
203
204  @Test
205  public void testChainWALEntryWithCellFilter() {
206    Entry userEntry = createEntry(null, a, b, c);
207    ChainWALEntryFilter filterSomeCells =
208      new ChainWALEntryFilter(new FilterSomeCellsWALCellFilter());
209    // since WALCellFilter filter cells with rowkey 'a'
210    assertEquals(createEntry(null, b, c), filterSomeCells.filter(userEntry));
211
212    Entry userEntry2 = createEntry(null, b, c, d);
213    // since there is no cell to get filtered, nothing should get filtered
214    assertEquals(userEntry2, filterSomeCells.filter(userEntry2));
215
216    // since we filter all the cells, we should get empty entry
217    ChainWALEntryFilter filterAllCells = new ChainWALEntryFilter(new FilterAllCellsWALCellFilter());
218    assertEquals(createEntry(null), filterAllCells.filter(userEntry));
219  }
220
221  @Test
222  public void testChainWALEmptyEntryWithCellFilter() {
223    Entry userEntry = createEntry(null, a, b, c);
224    ChainWALEmptyEntryFilter filterSomeCells =
225      new ChainWALEmptyEntryFilter(new FilterSomeCellsWALCellFilter());
226    // since WALCellFilter filter cells with rowkey 'a'
227    assertEquals(createEntry(null, b, c), filterSomeCells.filter(userEntry));
228
229    Entry userEntry2 = createEntry(null, b, c, d);
230    // since there is no cell to get filtered, nothing should get filtered
231    assertEquals(userEntry2, filterSomeCells.filter(userEntry2));
232
233    ChainWALEmptyEntryFilter filterAllCells =
234      new ChainWALEmptyEntryFilter(new FilterAllCellsWALCellFilter());
235    assertEquals(createEntry(null), filterAllCells.filter(userEntry));
236    // let's set the filter empty entry flag to true now for the above case
237    filterAllCells.setFilterEmptyEntry(true);
238    // since WALCellFilter filter all cells, whole entry should be filtered
239    assertEquals(null, filterAllCells.filter(userEntry));
240  }
241
242  @Test
243  public void testChainWALEntryFilter() {
244    Entry userEntry = createEntry(null, a, b, c);
245
246    ChainWALEntryFilter filter = new ChainWALEntryFilter(passFilter);
247    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
248
249    filter = new ChainWALEntryFilter(passFilter, passFilter);
250    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
251
252    filter = new ChainWALEntryFilter(passFilter, passFilter, passFilter);
253    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
254
255    filter = new ChainWALEntryFilter(nullFilter);
256    assertEquals(null, filter.filter(userEntry));
257
258    filter = new ChainWALEntryFilter(nullFilter, passFilter);
259    assertEquals(null, filter.filter(userEntry));
260
261    filter = new ChainWALEntryFilter(passFilter, nullFilter);
262    assertEquals(null, filter.filter(userEntry));
263
264    filter = new ChainWALEntryFilter(nullFilter, passFilter, nullFilter);
265    assertEquals(null, filter.filter(userEntry));
266
267    filter = new ChainWALEntryFilter(nullFilter, nullFilter);
268    assertEquals(null, filter.filter(userEntry));
269
270    // flatten
271    filter = new ChainWALEntryFilter(
272      new ChainWALEntryFilter(passFilter, new ChainWALEntryFilter(passFilter, passFilter),
273        new ChainWALEntryFilter(passFilter), new ChainWALEntryFilter(passFilter)),
274      new ChainWALEntryFilter(passFilter));
275    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
276
277    filter = new ChainWALEntryFilter(
278      new ChainWALEntryFilter(passFilter,
279        new ChainWALEntryFilter(passFilter, new ChainWALEntryFilter(nullFilter))),
280      new ChainWALEntryFilter(passFilter));
281    assertEquals(null, filter.filter(userEntry));
282  }
283
284  @Test
285  public void testNamespaceTableCfWALEntryFilter() {
286    ReplicationPeer peer = mock(ReplicationPeer.class);
287    ReplicationPeerConfigBuilder peerConfigBuilder = ReplicationPeerConfig.newBuilder();
288
289    // 1. replicate_all flag is false, no namespaces and table-cfs config
290    peerConfigBuilder.setReplicateAllUserTables(false).setNamespaces(null).setTableCFsMap(null);
291    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
292    Entry userEntry = createEntry(null, a, b, c);
293    ChainWALEntryFilter filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
294    assertEquals(null, filter.filter(userEntry));
295
296    // 2. replicate_all flag is false, and only config table-cfs in peer
297    // empty map
298    userEntry = createEntry(null, a, b, c);
299    Map<TableName, List<String>> tableCfs = new HashMap<>();
300    peerConfigBuilder.setReplicateAllUserTables(false).setTableCFsMap(tableCfs);
301    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
302    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
303    assertEquals(null, filter.filter(userEntry));
304
305    // table bar
306    userEntry = createEntry(null, a, b, c);
307    tableCfs = new HashMap<>();
308    tableCfs.put(TableName.valueOf("bar"), null);
309    peerConfigBuilder.setReplicateAllUserTables(false).setTableCFsMap(tableCfs);
310    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
311    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
312    assertEquals(null, filter.filter(userEntry));
313
314    // table foo:a
315    userEntry = createEntry(null, a, b, c);
316    tableCfs = new HashMap<>();
317    tableCfs.put(TableName.valueOf("foo"), Lists.newArrayList("a"));
318    peerConfigBuilder.setReplicateAllUserTables(false).setTableCFsMap(tableCfs);
319    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
320    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
321    assertEquals(createEntry(null, a), filter.filter(userEntry));
322
323    // table foo:a,c
324    userEntry = createEntry(null, a, b, c, d);
325    tableCfs = new HashMap<>();
326    tableCfs.put(TableName.valueOf("foo"), Lists.newArrayList("a", "c"));
327    peerConfigBuilder.setReplicateAllUserTables(false).setTableCFsMap(tableCfs);
328    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
329    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
330    assertEquals(createEntry(null, a, c), filter.filter(userEntry));
331
332    // 3. replicate_all flag is false, and only config namespaces in peer
333    when(peer.getTableCFs()).thenReturn(null);
334    // empty set
335    Set<String> namespaces = new HashSet<>();
336    peerConfigBuilder.setReplicateAllUserTables(false).setNamespaces(namespaces)
337      .setTableCFsMap(null);
338    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
339    userEntry = createEntry(null, a, b, c);
340    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
341    assertEquals(null, filter.filter(userEntry));
342
343    // namespace default
344    namespaces.add("default");
345    peerConfigBuilder.setReplicateAllUserTables(false).setNamespaces(namespaces);
346    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
347    userEntry = createEntry(null, a, b, c);
348    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
349    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
350
351    // namespace ns1
352    namespaces = new HashSet<>();
353    namespaces.add("ns1");
354    peerConfigBuilder.setReplicateAllUserTables(false).setNamespaces(namespaces);
355    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
356    userEntry = createEntry(null, a, b, c);
357    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
358    assertEquals(null, filter.filter(userEntry));
359
360    // 4. replicate_all flag is false, and config namespaces and table-cfs both
361    // Namespaces config should not confict with table-cfs config
362    namespaces = new HashSet<>();
363    tableCfs = new HashMap<>();
364    namespaces.add("ns1");
365    tableCfs.put(TableName.valueOf("foo"), Lists.newArrayList("a", "c"));
366    peerConfigBuilder.setReplicateAllUserTables(false).setNamespaces(namespaces)
367      .setTableCFsMap(tableCfs);
368    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
369    userEntry = createEntry(null, a, b, c);
370    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
371    assertEquals(createEntry(null, a, c), filter.filter(userEntry));
372
373    namespaces = new HashSet<>();
374    tableCfs = new HashMap<>();
375    namespaces.add("default");
376    tableCfs.put(TableName.valueOf("ns1:foo"), Lists.newArrayList("a", "c"));
377    peerConfigBuilder.setReplicateAllUserTables(false).setNamespaces(namespaces)
378      .setTableCFsMap(tableCfs);
379    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
380    userEntry = createEntry(null, a, b, c);
381    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
382    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
383
384    namespaces = new HashSet<>();
385    tableCfs = new HashMap<>();
386    namespaces.add("ns1");
387    tableCfs.put(TableName.valueOf("bar"), null);
388    peerConfigBuilder.setReplicateAllUserTables(false).setNamespaces(namespaces)
389      .setTableCFsMap(tableCfs);
390    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
391    userEntry = createEntry(null, a, b, c);
392    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
393    assertEquals(null, filter.filter(userEntry));
394  }
395
396  @Test
397  public void testNamespaceTableCfWALEntryFilter2() {
398    ReplicationPeer peer = mock(ReplicationPeer.class);
399    ReplicationPeerConfigBuilder peerConfigBuilder = ReplicationPeerConfig.newBuilder();
400
401    // 1. replicate_all flag is true
402    // and no exclude namespaces and no exclude table-cfs config
403    peerConfigBuilder.setReplicateAllUserTables(true).setExcludeNamespaces(null)
404      .setExcludeTableCFsMap(null);
405    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
406    Entry userEntry = createEntry(null, a, b, c);
407    ChainWALEntryFilter filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
408    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
409
410    // 2. replicate_all flag is true, and only config exclude namespaces
411    // empty set
412    Set<String> namespaces = new HashSet<String>();
413    peerConfigBuilder.setExcludeNamespaces(namespaces).setExcludeTableCFsMap(null);
414    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
415    userEntry = createEntry(null, a, b, c);
416    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
417    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
418
419    // exclude namespace default
420    namespaces.add("default");
421    peerConfigBuilder.setExcludeNamespaces(namespaces).setExcludeTableCFsMap(null);
422    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
423    userEntry = createEntry(null, a, b, c);
424    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
425    assertEquals(null, filter.filter(userEntry));
426
427    // exclude namespace ns1
428    namespaces = new HashSet<String>();
429    namespaces.add("ns1");
430    peerConfigBuilder.setExcludeNamespaces(namespaces).setExcludeTableCFsMap(null);
431    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
432    userEntry = createEntry(null, a, b, c);
433    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
434    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
435
436    // 3. replicate_all flag is true, and only config exclude table-cfs
437    // empty table-cfs map
438    Map<TableName, List<String>> tableCfs = new HashMap<TableName, List<String>>();
439    peerConfigBuilder.setExcludeNamespaces(null).setExcludeTableCFsMap(tableCfs);
440    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
441    userEntry = createEntry(null, a, b, c);
442    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
443    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
444
445    // exclude table bar
446    tableCfs = new HashMap<TableName, List<String>>();
447    tableCfs.put(TableName.valueOf("bar"), null);
448    peerConfigBuilder.setExcludeNamespaces(null).setExcludeTableCFsMap(tableCfs);
449    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
450    userEntry = createEntry(null, a, b, c);
451    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
452    assertEquals(createEntry(null, a, b, c), filter.filter(userEntry));
453
454    // exclude table foo:a
455    tableCfs = new HashMap<TableName, List<String>>();
456    tableCfs.put(TableName.valueOf("foo"), Lists.newArrayList("a"));
457    peerConfigBuilder.setExcludeNamespaces(null).setExcludeTableCFsMap(tableCfs);
458    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
459    userEntry = createEntry(null, a, b, c);
460    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
461    assertEquals(createEntry(null, b, c), filter.filter(userEntry));
462
463    // 4. replicate_all flag is true, and config exclude namespaces and table-cfs both
464    // exclude ns1 and table foo:a,c
465    namespaces = new HashSet<String>();
466    tableCfs = new HashMap<TableName, List<String>>();
467    namespaces.add("ns1");
468    tableCfs.put(TableName.valueOf("foo"), Lists.newArrayList("a", "c"));
469    peerConfigBuilder.setExcludeNamespaces(namespaces).setExcludeTableCFsMap(tableCfs);
470    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
471    userEntry = createEntry(null, a, b, c);
472    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
473    assertEquals(createEntry(null, b), filter.filter(userEntry));
474
475    // exclude namespace default and table ns1:bar
476    namespaces = new HashSet<String>();
477    tableCfs = new HashMap<TableName, List<String>>();
478    namespaces.add("default");
479    tableCfs.put(TableName.valueOf("ns1:bar"), new ArrayList<String>());
480    peerConfigBuilder.setExcludeNamespaces(namespaces).setExcludeTableCFsMap(tableCfs);
481    when(peer.getPeerConfig()).thenReturn(peerConfigBuilder.build());
482    userEntry = createEntry(null, a, b, c);
483    filter = new ChainWALEntryFilter(new NamespaceTableCfWALEntryFilter(peer));
484    assertEquals(null, filter.filter(userEntry));
485  }
486
487  private Entry createEntry(TreeMap<byte[], Integer> scopes, byte[]... kvs) {
488    WALKeyImpl key1 = new WALKeyImpl(new byte[0], TableName.valueOf("foo"),
489      EnvironmentEdgeManager.currentTime(), scopes);
490    WALEdit edit1 = new WALEdit();
491
492    for (byte[] kv : kvs) {
493      WALEditInternalHelper.addExtendedCell(edit1, new KeyValue(kv, kv, kv));
494    }
495    return new Entry(key1, edit1);
496  }
497
498  private void assertEquals(Entry e1, Entry e2) {
499    Assert.assertEquals(e1 == null, e2 == null);
500    if (e1 == null) {
501      return;
502    }
503
504    // do not compare WALKeys
505
506    // compare kvs
507    Assert.assertEquals(e1.getEdit() == null, e2.getEdit() == null);
508    if (e1.getEdit() == null) {
509      return;
510    }
511    List<Cell> cells1 = e1.getEdit().getCells();
512    List<Cell> cells2 = e2.getEdit().getCells();
513    Assert.assertEquals(cells1.size(), cells2.size());
514    for (int i = 0; i < cells1.size(); i++) {
515      CellComparatorImpl.COMPARATOR.compare(cells1.get(i), cells2.get(i));
516    }
517  }
518}