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.security.access;
019
020import static org.junit.jupiter.api.Assertions.assertThrows;
021import static org.mockito.Mockito.mock;
022import static org.mockito.Mockito.when;
023
024import java.io.IOException;
025import java.util.List;
026import org.apache.hadoop.fs.Path;
027import org.apache.hadoop.hbase.CompareOperator;
028import org.apache.hadoop.hbase.TableName;
029import org.apache.hadoop.hbase.WriteAttemptedOnReadOnlyClusterException;
030import org.apache.hadoop.hbase.client.Append;
031import org.apache.hadoop.hbase.client.CheckAndMutate;
032import org.apache.hadoop.hbase.client.CheckAndMutateResult;
033import org.apache.hadoop.hbase.client.Delete;
034import org.apache.hadoop.hbase.client.Durability;
035import org.apache.hadoop.hbase.client.Increment;
036import org.apache.hadoop.hbase.client.Mutation;
037import org.apache.hadoop.hbase.client.Put;
038import org.apache.hadoop.hbase.client.RegionInfo;
039import org.apache.hadoop.hbase.coprocessor.ObserverContext;
040import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
041import org.apache.hadoop.hbase.filter.ByteArrayComparable;
042import org.apache.hadoop.hbase.filter.Filter;
043import org.apache.hadoop.hbase.master.region.MasterRegionFactory;
044import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker;
045import org.apache.hadoop.hbase.regionserver.InternalScanner;
046import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
047import org.apache.hadoop.hbase.regionserver.ScanOptions;
048import org.apache.hadoop.hbase.regionserver.ScanType;
049import org.apache.hadoop.hbase.regionserver.Store;
050import org.apache.hadoop.hbase.regionserver.StoreFile;
051import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker;
052import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest;
053import org.apache.hadoop.hbase.testclassification.SecurityTests;
054import org.apache.hadoop.hbase.testclassification.SmallTests;
055import org.apache.hadoop.hbase.util.Bytes;
056import org.apache.hadoop.hbase.util.Pair;
057import org.apache.hadoop.hbase.wal.WALEdit;
058import org.apache.hadoop.hbase.wal.WALKey;
059import org.junit.jupiter.api.AfterEach;
060import org.junit.jupiter.api.BeforeEach;
061import org.junit.jupiter.api.Tag;
062import org.junit.jupiter.api.Test;
063
064// Tests methods of Region Observer interface which are implemented in ReadOnlyController,
065// by mocking the coprocessor environment and dependencies.
066// V1 and V2 means version 1 and version 2 of the coprocessor method signature.
067// For example, prePut has 2 versions:
068// V1: prePut(ObserverContext<RegionCoprocessorEnvironment> c, Put put, WALEdit edit)
069// V2: prePut(ObserverContext<RegionCoprocessorEnvironment> c, Put put, WALEdit edit, Durability durability)
070@Tag(SecurityTests.TAG)
071@Tag(SmallTests.TAG)
072public class TestReadOnlyControllerRegionObserver {
073
074  RegionReadOnlyController regionReadOnlyController;
075
076  // Region Coprocessor mocking variables
077  ObserverContext<RegionCoprocessorEnvironment> c, ctx;
078  RegionCoprocessorEnvironment env;
079  RegionInfo regionInfo;
080  Store store;
081  InternalScanner scanner;
082  ScanOptions options;
083  FlushLifeCycleTracker flushLifeCycleTracker;
084  List<StoreFile> candidates;
085  CompactionLifeCycleTracker compactionLifeCycleTracker;
086  ScanType scanType;
087  CompactionRequest compactionRequest;
088  TableName tableName;
089  Put put;
090  WALEdit edit;
091  Durability durability;
092  Delete delete;
093  MiniBatchOperationInProgress<Mutation> miniBatchOp;
094  byte[] row;
095  byte[] family;
096  byte[] qualifier;
097  Filter filter;
098  CompareOperator op;
099  ByteArrayComparable comparator;
100  boolean result;
101  CheckAndMutate checkAndMutate;
102  CheckAndMutateResult checkAndMutateResult;
103  Append append;
104  Increment increment;
105  RegionInfo info;
106  Path edits;
107  List<Pair<byte[], String>> familyPaths;
108  List<Pair<Path, Path>> pairs;
109  WALKey key;
110
111  @BeforeEach
112  public void setup() throws Exception {
113    regionReadOnlyController = new RegionReadOnlyController();
114
115    // mocking variables initialization
116    c = mock(ObserverContext.class);
117    // ctx is created to make naming variable in sync with the Observer interface
118    // methods where 'ctx' is used as the ObserverContext variable name instead of 'c'.
119    // otherwise both are one and the same
120    ctx = c;
121    env = mock(RegionCoprocessorEnvironment.class);
122    regionInfo = mock(RegionInfo.class);
123    store = mock(Store.class);
124    scanner = mock(InternalScanner.class);
125    options = mock(ScanOptions.class);
126    flushLifeCycleTracker = mock(FlushLifeCycleTracker.class);
127    compactionLifeCycleTracker = mock(CompactionLifeCycleTracker.class);
128    StoreFile sf1 = mock(StoreFile.class);
129    StoreFile sf2 = mock(StoreFile.class);
130    candidates = List.of(sf1, sf2);
131    scanType = ScanType.COMPACT_DROP_DELETES;
132    compactionRequest = mock(CompactionRequest.class);
133    tableName = TableName.valueOf("testTable");
134    put = mock(Put.class);
135    edit = mock(WALEdit.class);
136    durability = Durability.USE_DEFAULT;
137    delete = mock(Delete.class);
138    miniBatchOp = mock(MiniBatchOperationInProgress.class);
139    row = Bytes.toBytes("test-row");
140    family = Bytes.toBytes("test-family");
141    qualifier = Bytes.toBytes("test-qualifier");
142    filter = mock(Filter.class);
143    op = CompareOperator.NO_OP;
144    comparator = mock(ByteArrayComparable.class);
145    result = false;
146    checkAndMutate = CheckAndMutate
147      .newBuilder(Bytes.toBytes("test-row")).ifEquals(Bytes.toBytes("test-family"),
148        Bytes.toBytes("test-qualifier"), Bytes.toBytes("test-value"))
149      .build(new Put(Bytes.toBytes("test-row")));
150    checkAndMutateResult = mock(CheckAndMutateResult.class);
151    append = mock(Append.class);
152    increment = mock(Increment.class);
153    edits = mock(Path.class);
154    familyPaths = List.of(new Pair<>(Bytes.toBytes("test-family"), "/path/to/hfile1"),
155      new Pair<>(Bytes.toBytes("test-family"), "/path/to/hfile2"));
156    pairs = List.of(new Pair<>(mock(Path.class), mock(Path.class)),
157      new Pair<>(mock(Path.class), mock(Path.class)));
158    key = mock(WALKey.class);
159
160    // Linking the mocks:
161    when(c.getEnvironment()).thenReturn(env);
162    when(env.getRegionInfo()).thenReturn(regionInfo);
163    when(regionInfo.getTable()).thenReturn(tableName);
164    when(key.getTableName()).thenReturn(tableName);
165  }
166
167  @AfterEach
168  public void tearDown() throws Exception {
169
170  }
171
172  private void mockOperationForMetaTable() {
173    when(regionInfo.getTable()).thenReturn(TableName.META_TABLE_NAME);
174  }
175
176  private void mockOperationMasterStoreTable() {
177    when(regionInfo.getTable()).thenReturn(MasterRegionFactory.TABLE_NAME);
178  }
179
180  @Test
181  public void testPreFlushV1ReadOnlyException() {
182    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
183      regionReadOnlyController.preFlush(c, flushLifeCycleTracker);
184    });
185  }
186
187  @Test
188  public void testPreFlushV1ReadOnlyMetaNoException() throws IOException {
189    mockOperationForMetaTable();
190    regionReadOnlyController.preFlush(c, flushLifeCycleTracker);
191  }
192
193  @Test
194  public void testPreFlushV1ReadOnlyMasterStoreNoException() throws IOException {
195    mockOperationMasterStoreTable();
196    regionReadOnlyController.preFlush(c, flushLifeCycleTracker);
197  }
198
199  @Test
200  public void testPreFlushV2ReadOnlyException() {
201    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
202      regionReadOnlyController.preFlush(c, store, scanner, flushLifeCycleTracker);
203    });
204  }
205
206  @Test
207  public void testPreFlushV2ReadOnlyMetaNoException() throws IOException {
208    mockOperationForMetaTable();
209    regionReadOnlyController.preFlush(c, store, scanner, flushLifeCycleTracker);
210  }
211
212  @Test
213  public void testPreFlushV2ReadOnlyMasterStoreNoException() throws IOException {
214    mockOperationMasterStoreTable();
215    regionReadOnlyController.preFlush(c, store, scanner, flushLifeCycleTracker);
216  }
217
218  @Test
219  public void testPreFlushScannerOpenReadOnlyException() {
220    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
221      regionReadOnlyController.preFlushScannerOpen(c, store, options, flushLifeCycleTracker);
222    });
223  }
224
225  @Test
226  public void testPreFlushScannerOpenReadOnlyMetaNoException() throws IOException {
227    mockOperationForMetaTable();
228    regionReadOnlyController.preFlushScannerOpen(c, store, options, flushLifeCycleTracker);
229  }
230
231  @Test
232  public void testPreFlushScannerOpenReadOnlyMasterStoreNoException() throws IOException {
233    mockOperationMasterStoreTable();
234    regionReadOnlyController.preFlushScannerOpen(c, store, options, flushLifeCycleTracker);
235  }
236
237  @Test
238  public void testPreMemStoreCompactionReadOnlyException() {
239    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
240      regionReadOnlyController.preMemStoreCompaction(c, store);
241    });
242  }
243
244  @Test
245  public void testPreMemStoreCompactionCompactScannerOpenReadOnlyException() {
246    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
247      regionReadOnlyController.preMemStoreCompactionCompactScannerOpen(c, store, options);
248    });
249  }
250
251  @Test
252  public void testPreMemStoreCompactionCompactReadOnlyException() {
253    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
254      regionReadOnlyController.preMemStoreCompactionCompact(c, store, scanner);
255    });
256  }
257
258  @Test
259  public void testPreCompactSelectionReadOnlyException() {
260    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
261      regionReadOnlyController.preCompactSelection(c, store, candidates,
262        compactionLifeCycleTracker);
263    });
264  }
265
266  @Test
267  public void testPreCompactSelectionReadOnlyMetaNoException() throws IOException {
268    mockOperationForMetaTable();
269    regionReadOnlyController.preCompactSelection(c, store, candidates, compactionLifeCycleTracker);
270  }
271
272  @Test
273  public void testPreCompactSelectionReadOnlyMasterStoreNoException() throws IOException {
274    mockOperationMasterStoreTable();
275    regionReadOnlyController.preCompactSelection(c, store, candidates, compactionLifeCycleTracker);
276  }
277
278  @Test
279  public void testPreCompactScannerOpenReadOnlyException() {
280    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
281      regionReadOnlyController.preCompactScannerOpen(c, store, scanType, options,
282        compactionLifeCycleTracker, compactionRequest);
283    });
284  }
285
286  @Test
287  public void testPreCompactScannerOpenReadOnlyMetaNoException() throws IOException {
288    mockOperationForMetaTable();
289    regionReadOnlyController.preCompactScannerOpen(c, store, scanType, options,
290      compactionLifeCycleTracker, compactionRequest);
291  }
292
293  @Test
294  public void testPreCompactScannerOpenReadOnlyMasterStoreNoException() throws IOException {
295    mockOperationMasterStoreTable();
296    regionReadOnlyController.preCompactScannerOpen(c, store, scanType, options,
297      compactionLifeCycleTracker, compactionRequest);
298  }
299
300  @Test
301  public void testPreCompactReadOnlyException() {
302    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
303      regionReadOnlyController.preCompact(c, store, scanner, scanType, compactionLifeCycleTracker,
304        compactionRequest);
305    });
306  }
307
308  @Test
309  public void testPreCompactReadOnlyMetaNoException() throws IOException {
310    mockOperationForMetaTable();
311    regionReadOnlyController.preCompact(c, store, scanner, scanType, compactionLifeCycleTracker,
312      compactionRequest);
313  }
314
315  @Test
316  public void testPreCompactReadOnlyMasterStoreNoException() throws IOException {
317    mockOperationMasterStoreTable();
318    regionReadOnlyController.preCompact(c, store, scanner, scanType, compactionLifeCycleTracker,
319      compactionRequest);
320  }
321
322  @Test
323  public void testPrePutV1ReadOnlyException() {
324    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
325      regionReadOnlyController.prePut(c, put, edit);
326    });
327  }
328
329  @Test
330  public void testPrePutV1ReadOnlyMetaNoException() throws IOException {
331    mockOperationForMetaTable();
332    regionReadOnlyController.prePut(c, put, edit);
333  }
334
335  @Test
336  public void testPrePutV1ReadOnlyMasterStoreNoException() throws IOException {
337    mockOperationMasterStoreTable();
338    regionReadOnlyController.prePut(c, put, edit);
339  }
340
341  @Test
342  public void testPrePutV2ReadOnlyException() {
343    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
344      regionReadOnlyController.prePut(c, put, edit, durability);
345    });
346  }
347
348  @Test
349  public void testPrePutV2ReadOnlyMetaNoException() throws IOException {
350    mockOperationForMetaTable();
351    regionReadOnlyController.prePut(c, put, edit, durability);
352  }
353
354  @Test
355  public void testPrePutV2ReadOnlyMasterStoreNoException() throws IOException {
356    mockOperationMasterStoreTable();
357    regionReadOnlyController.prePut(c, put, edit, durability);
358  }
359
360  @Test
361  public void testPreDeleteV1ReadOnlyException() {
362    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
363      regionReadOnlyController.preDelete(c, delete, edit);
364    });
365  }
366
367  @Test
368  public void testPreDeleteV1ReadOnlyMetaNoException() throws IOException {
369    mockOperationForMetaTable();
370    regionReadOnlyController.preDelete(c, delete, edit);
371  }
372
373  @Test
374  public void testPreDeleteV1ReadOnlyMasterStoreNoException() throws IOException {
375    mockOperationMasterStoreTable();
376    regionReadOnlyController.preDelete(c, delete, edit);
377  }
378
379  @Test
380  public void testPreDeleteV2ReadOnlyException() {
381    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
382      regionReadOnlyController.preDelete(c, delete, edit, durability);
383    });
384  }
385
386  @Test
387  public void testPreDeleteV2ReadOnlyMetaNoException() throws IOException {
388    mockOperationForMetaTable();
389    regionReadOnlyController.preDelete(c, delete, edit, durability);
390  }
391
392  @Test
393  public void testPreDeleteV2ReadOnlyMasterStoreNoException() throws IOException {
394    mockOperationMasterStoreTable();
395    regionReadOnlyController.preDelete(c, delete, edit, durability);
396  }
397
398  @Test
399  public void testPreBatchMutateReadOnlyException() {
400    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
401      regionReadOnlyController.preBatchMutate(c, miniBatchOp);
402    });
403  }
404
405  @Test
406  public void testPreBatchMutateReadOnlyMetaNoException() throws IOException {
407    mockOperationForMetaTable();
408    regionReadOnlyController.preBatchMutate(c, miniBatchOp);
409  }
410
411  @Test
412  public void testPreBatchMutateReadOnlyMasterStoreNoException() throws IOException {
413    mockOperationMasterStoreTable();
414    regionReadOnlyController.preBatchMutate(c, miniBatchOp);
415  }
416
417  @Test
418  public void testPreCheckAndPutV1ReadOnlyException() {
419    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
420      regionReadOnlyController.preCheckAndPut(c, row, family, qualifier, op, comparator, put,
421        result);
422    });
423  }
424
425  @Test
426  public void testPreCheckAndPutV1ReadOnlyMetaNoException() throws IOException {
427    mockOperationForMetaTable();
428    regionReadOnlyController.preCheckAndPut(c, row, family, qualifier, op, comparator, put, result);
429  }
430
431  @Test
432  public void testPreCheckAndPutV1ReadOnlyMasterStoreNoException() throws IOException {
433    mockOperationMasterStoreTable();
434    regionReadOnlyController.preCheckAndPut(c, row, family, qualifier, op, comparator, put, result);
435  }
436
437  @Test
438  public void testPreCheckAndPutV2ReadOnlyException() {
439    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
440      regionReadOnlyController.preCheckAndPut(c, row, filter, put, result);
441    });
442  }
443
444  @Test
445  public void testPreCheckAndPutV2ReadOnlyMetaNoException() throws IOException {
446    mockOperationForMetaTable();
447    regionReadOnlyController.preCheckAndPut(c, row, filter, put, result);
448  }
449
450  @Test
451  public void testPreCheckAndPutV2ReadOnlyMasterStoreNoException() throws IOException {
452    mockOperationMasterStoreTable();
453    regionReadOnlyController.preCheckAndPut(c, row, filter, put, result);
454  }
455
456  @Test
457  public void testPreCheckAndPutAfterRowLockV1ReadOnlyException() {
458    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
459      regionReadOnlyController.preCheckAndPutAfterRowLock(c, row, family, qualifier, op, comparator,
460        put, result);
461    });
462  }
463
464  @Test
465  public void testPreCheckAndPutAfterRowLockV1ReadOnlyMetaNoException() throws IOException {
466    mockOperationForMetaTable();
467    regionReadOnlyController.preCheckAndPutAfterRowLock(c, row, family, qualifier, op, comparator,
468      put, result);
469  }
470
471  @Test
472  public void testPreCheckAndPutAfterRowLockV1ReadOnlyMasterStoreNoException() throws IOException {
473    mockOperationMasterStoreTable();
474    regionReadOnlyController.preCheckAndPutAfterRowLock(c, row, family, qualifier, op, comparator,
475      put, result);
476  }
477
478  @Test
479  public void testPreCheckAndPutAfterRowLockV2ReadOnlyException() {
480    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
481      regionReadOnlyController.preCheckAndPutAfterRowLock(c, row, filter, put, result);
482    });
483  }
484
485  @Test
486  public void testPreCheckAndPutAfterRowLockV2ReadOnlyMetaNoException() throws IOException {
487    mockOperationForMetaTable();
488    regionReadOnlyController.preCheckAndPutAfterRowLock(c, row, filter, put, result);
489  }
490
491  @Test
492  public void testPreCheckAndPutAfterRowLockV2ReadOnlyMasterStoreNoException() throws IOException {
493    mockOperationMasterStoreTable();
494    regionReadOnlyController.preCheckAndPutAfterRowLock(c, row, filter, put, result);
495  }
496
497  @Test
498  public void testPreCheckAndDeleteV1ReadOnlyException() {
499    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
500      regionReadOnlyController.preCheckAndDelete(c, row, family, qualifier, op, comparator, delete,
501        result);
502    });
503  }
504
505  @Test
506  public void testPreCheckAndDeleteV1ReadOnlyMetaNoException() throws IOException {
507    mockOperationForMetaTable();
508    regionReadOnlyController.preCheckAndDelete(c, row, family, qualifier, op, comparator, delete,
509      result);
510  }
511
512  @Test
513  public void testPreCheckAndDeleteV1ReadOnlyMasterStoreNoException() throws IOException {
514    mockOperationMasterStoreTable();
515    regionReadOnlyController.preCheckAndDelete(c, row, family, qualifier, op, comparator, delete,
516      result);
517  }
518
519  @Test
520  public void testPreCheckAndDeleteV2ReadOnlyException() {
521    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
522      regionReadOnlyController.preCheckAndDelete(c, row, filter, delete, result);
523    });
524  }
525
526  @Test
527  public void testPreCheckAndDeleteV2ReadOnlyMetaNoException() throws IOException {
528    mockOperationForMetaTable();
529    regionReadOnlyController.preCheckAndDelete(c, row, filter, delete, result);
530  }
531
532  @Test
533  public void testPreCheckAndDeleteV2ReadOnlyMasterStoreNoException() throws IOException {
534    mockOperationMasterStoreTable();
535    regionReadOnlyController.preCheckAndDelete(c, row, filter, delete, result);
536  }
537
538  @Test
539  public void testPreCheckAndDeleteAfterRowLockV1ReadOnlyException() {
540    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
541      regionReadOnlyController.preCheckAndDeleteAfterRowLock(c, row, family, qualifier, op,
542        comparator, delete, result);
543    });
544  }
545
546  @Test
547  public void testPreCheckAndDeleteAfterRowLockV1ReadOnlyMetaNoException() throws IOException {
548    mockOperationForMetaTable();
549    regionReadOnlyController.preCheckAndDeleteAfterRowLock(c, row, family, qualifier, op,
550      comparator, delete, result);
551  }
552
553  @Test
554  public void testPreCheckAndDeleteAfterRowLockV1ReadOnlyMasterStoreNoException()
555    throws IOException {
556    mockOperationMasterStoreTable();
557    regionReadOnlyController.preCheckAndDeleteAfterRowLock(c, row, family, qualifier, op,
558      comparator, delete, result);
559  }
560
561  @Test
562  public void testPreCheckAndDeleteAfterRowLockV2ReadOnlyException() {
563    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
564      regionReadOnlyController.preCheckAndDeleteAfterRowLock(c, row, filter, delete, result);
565    });
566  }
567
568  @Test
569  public void testPreCheckAndDeleteAfterRowLockV2ReadOnlyMetaNoException() throws IOException {
570    mockOperationForMetaTable();
571    regionReadOnlyController.preCheckAndDeleteAfterRowLock(c, row, filter, delete, result);
572  }
573
574  @Test
575  public void testPreCheckAndDeleteAfterRowLockV2ReadOnlyMasterStoreNoException()
576    throws IOException {
577    mockOperationMasterStoreTable();
578    regionReadOnlyController.preCheckAndDeleteAfterRowLock(c, row, filter, delete, result);
579  }
580
581  @Test
582  public void testPreCheckAndMutateReadOnlyException() {
583    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
584      regionReadOnlyController.preCheckAndMutate(c, checkAndMutate, checkAndMutateResult);
585    });
586  }
587
588  @Test
589  public void testPreCheckAndMutateAfterRowLockReadOnlyException() {
590    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
591      regionReadOnlyController.preCheckAndMutateAfterRowLock(c, checkAndMutate,
592        checkAndMutateResult);
593    });
594  }
595
596  @Test
597  public void testPreAppendV1ReadOnlyException() {
598    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
599      regionReadOnlyController.preAppend(c, append);
600    });
601  }
602
603  @Test
604  public void testPreAppendV2ReadOnlyException() {
605    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
606      regionReadOnlyController.preAppend(c, append, edit);
607    });
608  }
609
610  @Test
611  public void testPreAppendAfterRowLockReadOnlyException() {
612    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
613      regionReadOnlyController.preAppendAfterRowLock(c, append);
614    });
615  }
616
617  @Test
618  public void testPreIncrementV1ReadOnlyException() {
619    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
620      regionReadOnlyController.preIncrement(c, increment);
621    });
622  }
623
624  @Test
625  public void testPreIncrementV2ReadOnlyException() {
626    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
627      regionReadOnlyController.preIncrement(c, increment, edit);
628    });
629  }
630
631  @Test
632  public void testPreIncrementAfterRowLockReadOnlyException() {
633    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
634      regionReadOnlyController.preIncrementAfterRowLock(c, increment);
635    });
636  }
637
638  @Test
639  public void testPreReplayWALsReadOnlyException() {
640    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
641      regionReadOnlyController.preReplayWALs(ctx, info, edits);
642    });
643  }
644
645  @Test
646  public void testPreReplayWALsReadOnlyMetaNoException() throws IOException {
647    mockOperationForMetaTable();
648    regionReadOnlyController.preReplayWALs(ctx, info, edits);
649  }
650
651  @Test
652  public void testPreReplayWALsReadOnlyMasterStoreNoException() throws IOException {
653    mockOperationMasterStoreTable();
654    regionReadOnlyController.preReplayWALs(ctx, info, edits);
655  }
656
657  @Test
658  public void testPreBulkLoadHFileReadOnlyException() {
659    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
660      regionReadOnlyController.preBulkLoadHFile(ctx, familyPaths);
661    });
662  }
663
664  @Test
665  public void testPreCommitStoreFileReadOnlyException() {
666    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
667      regionReadOnlyController.preCommitStoreFile(ctx, family, pairs);
668    });
669  }
670
671  @Test
672  public void testPreWALAppendReadOnlyException() {
673    assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> {
674      regionReadOnlyController.preWALAppend(ctx, key, edit);
675    });
676  }
677
678  @Test
679  public void testPreWALAppendReadOnlyMetaNoException() throws IOException {
680    when(key.getTableName()).thenReturn(TableName.META_TABLE_NAME);
681    regionReadOnlyController.preWALAppend(ctx, key, edit);
682  }
683
684  @Test
685  public void testPreWALAppendReadOnlyMasterStoreNoException() throws IOException {
686    when(key.getTableName()).thenReturn(MasterRegionFactory.TABLE_NAME);
687    regionReadOnlyController.preWALAppend(ctx, key, edit);
688  }
689}