Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

ChunkIndexTest.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * Copyright (C) 2011, Google Inc.
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.storage.dht;
  44. import static org.junit.Assert.assertEquals;
  45. import static org.junit.Assert.assertTrue;
  46. import java.util.ArrayList;
  47. import java.util.List;
  48. import org.eclipse.jgit.lib.MutableObjectId;
  49. import org.eclipse.jgit.lib.ObjectId;
  50. import org.eclipse.jgit.transport.PackedObjectInfo;
  51. import org.eclipse.jgit.util.NB;
  52. import org.junit.Test;
  53. public class ChunkIndexTest {
  54. @Test
  55. public void testSingleObject_NotFound() throws DhtException {
  56. List<PackedObjectInfo> objs = list(object(1, 1));
  57. ChunkIndex idx = index(objs);
  58. assertEquals(-1, idx.findOffset(ObjectId.zeroId()));
  59. }
  60. @Test
  61. public void testSingleObject_Offset1() throws DhtException {
  62. assertEquals(header(0, 1), header(list(object(1, 0))));
  63. List<PackedObjectInfo> objs = list(object(0x1200, 255));
  64. ChunkIndex idx = index(objs);
  65. assertEquals(header(0, 1), header(objs));
  66. assertEquals(1, idx.getObjectCount());
  67. assertEquals(2 + 20 + 1, idx.getIndexSize());
  68. assertEquals(objs.get(0), idx.getObjectId(0));
  69. assertEquals(objs.get(0).getOffset(), idx.getOffset(0));
  70. assertEquals(objs.get(0).getOffset(), idx.findOffset(objs.get(0)));
  71. }
  72. @Test
  73. public void testSingleObject_Offset2() throws DhtException {
  74. assertEquals(header(0, 2), header(list(object(1, 1 << 8))));
  75. List<PackedObjectInfo> objs = list(object(0x1200, 0xab34));
  76. ChunkIndex idx = index(objs);
  77. assertEquals(header(0, 2), header(objs));
  78. assertEquals(1, idx.getObjectCount());
  79. assertEquals(2 + 20 + 2, idx.getIndexSize());
  80. assertEquals(objs.get(0), idx.getObjectId(0));
  81. assertEquals(objs.get(0).getOffset(), idx.getOffset(0));
  82. assertEquals(objs.get(0).getOffset(), idx.findOffset(objs.get(0)));
  83. }
  84. @Test
  85. public void testSingleObject_Offset3() throws DhtException {
  86. assertEquals(header(0, 3), header(list(object(1, 1 << 16))));
  87. List<PackedObjectInfo> objs = list(object(0x1200, 0xab1234));
  88. ChunkIndex idx = index(objs);
  89. assertEquals(header(0, 3), header(objs));
  90. assertEquals(1, idx.getObjectCount());
  91. assertEquals(2 + 20 + 3, idx.getIndexSize());
  92. assertEquals(objs.get(0), idx.getObjectId(0));
  93. assertEquals(objs.get(0).getOffset(), idx.getOffset(0));
  94. assertEquals(objs.get(0).getOffset(), idx.findOffset(objs.get(0)));
  95. }
  96. @Test
  97. public void testSingleObject_Offset4() throws DhtException {
  98. assertEquals(header(0, 4), header(list(object(1, 1 << 24))));
  99. List<PackedObjectInfo> objs = list(object(0x1200, 0x7bcdef42));
  100. ChunkIndex idx = index(objs);
  101. assertEquals(header(0, 4), header(objs));
  102. assertEquals(1, idx.getObjectCount());
  103. assertEquals(objs.get(0), idx.getObjectId(0));
  104. assertEquals(2 + 20 + 4, idx.getIndexSize());
  105. assertEquals(objs.get(0).getOffset(), idx.getOffset(0));
  106. assertEquals(objs.get(0).getOffset(), idx.findOffset(objs.get(0)));
  107. }
  108. @Test
  109. public void testObjects3() throws DhtException {
  110. List<PackedObjectInfo> objs = objects(2, 3, 1);
  111. ChunkIndex idx = index(objs);
  112. assertEquals(header(0, 1), header(objs));
  113. assertEquals(3, idx.getObjectCount());
  114. assertEquals(2 + 3 * 20 + 3 * 1, idx.getIndexSize());
  115. assertTrue(isSorted(objs));
  116. for (int i = 0; i < objs.size(); i++) {
  117. assertEquals(objs.get(i), idx.getObjectId(i));
  118. assertEquals(objs.get(i).getOffset(), idx.getOffset(i));
  119. assertEquals(objs.get(i).getOffset(), idx.findOffset(objs.get(i)));
  120. }
  121. }
  122. @Test
  123. public void testObjects255_SameBucket() throws DhtException {
  124. int[] ints = new int[255];
  125. for (int i = 0; i < 255; i++)
  126. ints[i] = i;
  127. List<PackedObjectInfo> objs = objects(ints);
  128. ChunkIndex idx = index(objs);
  129. assertEquals(header(1, 2), header(objs));
  130. assertEquals(255, idx.getObjectCount());
  131. assertEquals(2 + 256 + 255 * 20 + 255 * 2 //
  132. + 12 + 4 * 256, idx.getIndexSize());
  133. assertTrue(isSorted(objs));
  134. for (int i = 0; i < objs.size(); i++) {
  135. assertEquals(objs.get(i), idx.getObjectId(i));
  136. assertEquals(objs.get(i).getOffset(), idx.getOffset(i));
  137. assertEquals(objs.get(i).getOffset(), idx.findOffset(objs.get(i)));
  138. }
  139. }
  140. @Test
  141. public void testObjects512_ManyBuckets() throws DhtException {
  142. int[] ints = new int[512];
  143. for (int i = 0; i < 256; i++) {
  144. ints[i] = (i << 8) | 0;
  145. ints[i + 256] = (i << 8) | 1;
  146. }
  147. List<PackedObjectInfo> objs = objects(ints);
  148. ChunkIndex idx = index(objs);
  149. assertEquals(header(1, 2), header(objs));
  150. assertEquals(512, idx.getObjectCount());
  151. assertEquals(2 + 256 + 512 * 20 + 512 * 2 //
  152. + 12 + 4 * 256, idx.getIndexSize());
  153. assertTrue(isSorted(objs));
  154. for (int i = 0; i < objs.size(); i++) {
  155. assertEquals(objs.get(i), idx.getObjectId(i));
  156. assertEquals(objs.get(i).getOffset(), idx.getOffset(i));
  157. assertEquals(objs.get(i).getOffset(), idx.findOffset(objs.get(i)));
  158. }
  159. }
  160. @Test
  161. public void testFanout2() throws DhtException {
  162. List<PackedObjectInfo> objs = new ArrayList<PackedObjectInfo>(65280);
  163. MutableObjectId idBuf = new MutableObjectId();
  164. for (int i = 0; i < 256; i++) {
  165. idBuf.setByte(2, i & 0xff);
  166. for (int j = 0; j < 255; j++) {
  167. idBuf.setByte(3, j & 0xff);
  168. PackedObjectInfo oe = new PackedObjectInfo(idBuf);
  169. oe.setOffset((i << 8) | j);
  170. objs.add(oe);
  171. }
  172. }
  173. ChunkIndex idx = index(objs);
  174. assertEquals(header(2, 2), header(objs));
  175. assertEquals(256 * 255, idx.getObjectCount());
  176. assertTrue(isSorted(objs));
  177. for (int i = 0; i < objs.size(); i++) {
  178. assertEquals(objs.get(i), idx.getObjectId(i));
  179. assertEquals(objs.get(i).getOffset(), idx.getOffset(i));
  180. assertEquals(objs.get(i).getOffset(), idx.findOffset(objs.get(i)));
  181. }
  182. }
  183. @Test
  184. public void testFanout3() throws DhtException {
  185. List<PackedObjectInfo> objs = new ArrayList<PackedObjectInfo>(1 << 16);
  186. MutableObjectId idBuf = new MutableObjectId();
  187. for (int i = 0; i < 256; i++) {
  188. idBuf.setByte(2, i & 0xff);
  189. for (int j = 0; j < 256; j++) {
  190. idBuf.setByte(3, j & 0xff);
  191. PackedObjectInfo oe = new PackedObjectInfo(idBuf);
  192. oe.setOffset((i << 8) | j);
  193. objs.add(oe);
  194. }
  195. }
  196. ChunkIndex idx = index(objs);
  197. assertEquals(header(3, 2), header(objs));
  198. assertEquals(256 * 256, idx.getObjectCount());
  199. assertTrue(isSorted(objs));
  200. for (int i = 0; i < objs.size(); i++) {
  201. assertEquals(objs.get(i), idx.getObjectId(i));
  202. assertEquals(objs.get(i).getOffset(), idx.getOffset(i));
  203. assertEquals(objs.get(i).getOffset(), idx.findOffset(objs.get(i)));
  204. }
  205. }
  206. @Test
  207. public void testObjects65280_ManyBuckets() throws DhtException {
  208. List<PackedObjectInfo> objs = new ArrayList<PackedObjectInfo>(65280);
  209. MutableObjectId idBuf = new MutableObjectId();
  210. for (int i = 0; i < 256; i++) {
  211. idBuf.setByte(0, i & 0xff);
  212. for (int j = 0; j < 255; j++) {
  213. idBuf.setByte(3, j & 0xff);
  214. PackedObjectInfo oe = new PackedObjectInfo(idBuf);
  215. oe.setOffset((i << 8) | j);
  216. objs.add(oe);
  217. }
  218. }
  219. ChunkIndex idx = index(objs);
  220. assertEquals(header(1, 2), header(objs));
  221. assertEquals(65280, idx.getObjectCount());
  222. assertTrue(isSorted(objs));
  223. for (int i = 0; i < objs.size(); i++) {
  224. assertEquals(objs.get(i), idx.getObjectId(i));
  225. assertEquals(objs.get(i).getOffset(), idx.getOffset(i));
  226. assertEquals(objs.get(i).getOffset(), idx.findOffset(objs.get(i)));
  227. }
  228. }
  229. private boolean isSorted(List<PackedObjectInfo> objs) {
  230. PackedObjectInfo last = objs.get(0);
  231. for (int i = 1; i < objs.size(); i++) {
  232. PackedObjectInfo oe = objs.get(i);
  233. if (oe.compareTo(last) <= 0)
  234. return false;
  235. }
  236. return true;
  237. }
  238. private List<PackedObjectInfo> list(PackedObjectInfo... all) {
  239. List<PackedObjectInfo> objs = new ArrayList<PackedObjectInfo>();
  240. for (PackedObjectInfo o : all)
  241. objs.add(o);
  242. return objs;
  243. }
  244. private int header(int fanoutTable, int offsetTable) {
  245. return (0x01 << 8) | (fanoutTable << 3) | offsetTable;
  246. }
  247. private int header(List<PackedObjectInfo> objs) {
  248. byte[] index = ChunkIndex.create(objs);
  249. return NB.decodeUInt16(index, 0);
  250. }
  251. private ChunkIndex index(List<PackedObjectInfo> objs) throws DhtException {
  252. ChunkKey key = null;
  253. byte[] index = ChunkIndex.create(objs);
  254. return ChunkIndex.fromBytes(key, index, 0, index.length);
  255. }
  256. private List<PackedObjectInfo> objects(int... values) {
  257. List<PackedObjectInfo> objs = new ArrayList<PackedObjectInfo>();
  258. for (int i = 0; i < values.length; i++)
  259. objs.add(object(values[i], i * 10));
  260. return objs;
  261. }
  262. private PackedObjectInfo object(int id, int off) {
  263. MutableObjectId idBuf = new MutableObjectId();
  264. idBuf.setByte(0, (id >>> 8) & 0xff);
  265. idBuf.setByte(1, id & 0xff);
  266. PackedObjectInfo obj = new PackedObjectInfo(idBuf);
  267. obj.setOffset(off);
  268. return obj;
  269. }
  270. }