1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.mapreduce;
20
21 import com.google.common.collect.ImmutableList;
22 import com.google.common.collect.ImmutableMap;
23 import com.google.common.collect.Lists;
24 import com.google.common.collect.Maps;
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.fs.FileSystem;
27 import org.apache.hadoop.fs.Path;
28 import org.apache.hadoop.hbase.client.Scan;
29 import org.apache.hadoop.hbase.testclassification.SmallTests;
30 import org.apache.hadoop.hbase.util.Bytes;
31 import org.apache.hadoop.hbase.util.FSUtils;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.junit.experimental.categories.Category;
35 import org.mockito.Mockito;
36
37 import java.io.IOException;
38 import java.util.Collection;
39 import java.util.List;
40 import java.util.Map;
41
42 import static org.junit.Assert.assertEquals;
43 import static org.mockito.Matchers.any;
44 import static org.mockito.Matchers.eq;
45 import static org.mockito.Mockito.doNothing;
46 import static org.mockito.Mockito.verify;
47
48 @Category({ SmallTests.class })
49 public class TestMultiTableSnapshotInputFormatImpl {
50
51 private MultiTableSnapshotInputFormatImpl subject;
52 private Map<String, Collection<Scan>> snapshotScans;
53 private Path restoreDir;
54 private Configuration conf;
55 private Path rootDir;
56
57 @Before
58 public void setUp() throws Exception {
59 this.subject = Mockito.spy(new MultiTableSnapshotInputFormatImpl());
60
61
62
63
64
65
66
67
68
69 doNothing().when(this.subject).
70 restoreSnapshot(any(Configuration.class), any(String.class), any(Path.class),
71 any(Path.class), any(FileSystem.class));
72
73 this.conf = new Configuration();
74 this.rootDir = new Path("file:///test-root-dir");
75 FSUtils.setRootDir(conf, rootDir);
76 this.snapshotScans = ImmutableMap.<String, Collection<Scan>>of("snapshot1",
77 ImmutableList.of(new Scan(Bytes.toBytes("1"), Bytes.toBytes("2"))), "snapshot2",
78 ImmutableList.of(new Scan(Bytes.toBytes("3"), Bytes.toBytes("4")),
79 new Scan(Bytes.toBytes("5"), Bytes.toBytes("6"))));
80
81 this.restoreDir = new Path(FSUtils.getRootDir(conf), "restore-dir");
82
83 }
84
85 public void callSetInput() throws IOException {
86 subject.setInput(this.conf, snapshotScans, restoreDir);
87 }
88
89 public Map<String, Collection<ScanWithEquals>> toScanWithEquals(
90 Map<String, Collection<Scan>> snapshotScans) throws IOException {
91 Map<String, Collection<ScanWithEquals>> rtn = Maps.newHashMap();
92
93 for (Map.Entry<String, Collection<Scan>> entry : snapshotScans.entrySet()) {
94 List<ScanWithEquals> scans = Lists.newArrayList();
95
96 for (Scan scan : entry.getValue()) {
97 scans.add(new ScanWithEquals(scan));
98 }
99 rtn.put(entry.getKey(), scans);
100 }
101
102 return rtn;
103 }
104
105 public static class ScanWithEquals {
106
107 private final String startRow;
108 private final String stopRow;
109
110
111
112
113
114
115
116 public ScanWithEquals(Scan scan) throws IOException {
117 this.startRow = Bytes.toStringBinary(scan.getStartRow());
118 this.stopRow = Bytes.toStringBinary(scan.getStopRow());
119 }
120
121 @Override
122 public int hashCode() {
123 final int prime = 31;
124 int result = 1;
125 result = prime * result + ((startRow == null) ? 0 : startRow.hashCode());
126 result = prime * result + ((stopRow == null) ? 0 : stopRow.hashCode());
127 return result;
128 }
129
130 @Override
131 public boolean equals(Object obj) {
132 if (this == obj) {
133 return true;
134 }
135 if (obj == null) {
136 return false;
137 }
138 if (getClass() != obj.getClass()) {
139 return false;
140 }
141 ScanWithEquals other = (ScanWithEquals) obj;
142 if (startRow == null) {
143 if (other.startRow != null) {
144 return false;
145 }
146 } else if (!startRow.equals(other.startRow)) {
147 return false;
148 }
149 if (stopRow == null) {
150 if (other.stopRow != null) {
151 return false;
152 }
153 } else if (!stopRow.equals(other.stopRow)) {
154 return false;
155 }
156 return true;
157 }
158
159 @Override
160 public String toString() {
161 return com.google.common.base.Objects.toStringHelper(this).add("startRow", startRow)
162 .add("stopRow", stopRow).toString();
163 }
164 }
165
166 @Test
167 public void testSetInputSetsSnapshotToScans() throws Exception {
168
169 callSetInput();
170
171 Map<String, Collection<Scan>> actual = subject.getSnapshotsToScans(conf);
172
173
174 Map<String, Collection<ScanWithEquals>> actualWithEquals = toScanWithEquals(actual);
175 Map<String, Collection<ScanWithEquals>> expectedWithEquals = toScanWithEquals(snapshotScans);
176
177 assertEquals(expectedWithEquals, actualWithEquals);
178 }
179
180 @Test
181 public void testSetInputPushesRestoreDirectories() throws Exception {
182 callSetInput();
183
184 Map<String, Path> restoreDirs = subject.getSnapshotDirs(conf);
185
186 assertEquals(this.snapshotScans.keySet(), restoreDirs.keySet());
187 }
188
189 @Test
190 public void testSetInputCreatesRestoreDirectoriesUnderRootRestoreDir() throws Exception {
191 callSetInput();
192
193 Map<String, Path> restoreDirs = subject.getSnapshotDirs(conf);
194
195 for (Path snapshotDir : restoreDirs.values()) {
196 assertEquals("Expected " + snapshotDir + " to be a child of " + restoreDir, restoreDir,
197 snapshotDir.getParent());
198 }
199 }
200
201 @Test
202 public void testSetInputRestoresSnapshots() throws Exception {
203 callSetInput();
204
205 Map<String, Path> snapshotDirs = subject.getSnapshotDirs(conf);
206
207 for (Map.Entry<String, Path> entry : snapshotDirs.entrySet()) {
208 verify(this.subject).restoreSnapshot(eq(this.conf), eq(entry.getKey()), eq(this.rootDir),
209 eq(entry.getValue()), any(FileSystem.class));
210 }
211 }
212 }