You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FileSourceDaoTest.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.db.source;
  21. import com.google.common.collect.ImmutableList;
  22. import com.google.common.collect.ImmutableSet;
  23. import java.io.IOException;
  24. import java.io.Reader;
  25. import java.util.ArrayList;
  26. import java.util.List;
  27. import java.util.Optional;
  28. import java.util.Random;
  29. import java.util.function.Consumer;
  30. import java.util.stream.Collectors;
  31. import java.util.stream.IntStream;
  32. import javax.annotation.Nullable;
  33. import org.apache.commons.io.IOUtils;
  34. import org.apache.ibatis.session.ResultContext;
  35. import org.apache.ibatis.session.ResultHandler;
  36. import org.junit.Rule;
  37. import org.junit.Test;
  38. import org.sonar.api.utils.System2;
  39. import org.sonar.db.DbSession;
  40. import org.sonar.db.DbTester;
  41. import org.sonar.db.component.ComponentDto;
  42. import org.sonar.db.organization.OrganizationDto;
  43. import static com.google.common.collect.ImmutableList.of;
  44. import static java.util.Collections.emptyList;
  45. import static java.util.Collections.emptySet;
  46. import static java.util.Collections.singletonList;
  47. import static org.assertj.core.api.Assertions.assertThat;
  48. import static org.assertj.core.api.Assertions.fail;
  49. import static org.sonar.db.component.ComponentTesting.newFileDto;
  50. public class FileSourceDaoTest {
  51. @Rule
  52. public DbTester dbTester = DbTester.create(System2.INSTANCE);
  53. private DbSession dbSession = dbTester.getSession();
  54. private FileSourceDao underTest = dbTester.getDbClient().fileSourceDao();
  55. @Test
  56. public void select() {
  57. dbTester.prepareDbUnit(getClass(), "shared.xml");
  58. FileSourceDto fileSourceDto = underTest.selectByFileUuid(dbSession, "FILE1_UUID");
  59. assertThat(fileSourceDto.getBinaryData()).isNotEmpty();
  60. assertThat(fileSourceDto.getDataHash()).isEqualTo("hash");
  61. assertThat(fileSourceDto.getProjectUuid()).isEqualTo("PRJ_UUID");
  62. assertThat(fileSourceDto.getFileUuid()).isEqualTo("FILE1_UUID");
  63. assertThat(fileSourceDto.getCreatedAt()).isEqualTo(1500000000000L);
  64. assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(1500000000000L);
  65. assertThat(fileSourceDto.getRevision()).isEqualTo("123456789");
  66. assertThat(fileSourceDto.getLineHashesVersion()).isEqualTo(0);
  67. }
  68. @Test
  69. public void select_line_hashes() {
  70. dbTester.prepareDbUnit(getClass(), "shared.xml");
  71. ReaderToStringConsumer fn = new ReaderToStringConsumer();
  72. underTest.readLineHashesStream(dbSession, "FILE1_UUID", fn);
  73. assertThat(fn.result).isEqualTo("ABC\\nDEF\\nGHI");
  74. }
  75. @Test
  76. public void no_line_hashes_on_unknown_file() {
  77. dbTester.prepareDbUnit(getClass(), "shared.xml");
  78. ReaderToStringConsumer fn = new ReaderToStringConsumer();
  79. underTest.readLineHashesStream(dbSession, "unknown", fn);
  80. assertThat(fn.result).isNull();
  81. }
  82. @Test
  83. public void no_line_hashes_when_only_test_data() {
  84. dbTester.prepareDbUnit(getClass(), "no_line_hashes_when_only_test_data.xml");
  85. ReaderToStringConsumer fn = new ReaderToStringConsumer();
  86. underTest.readLineHashesStream(dbSession, "FILE1_UUID", fn);
  87. assertThat(fn.result).isNull();
  88. }
  89. @Test
  90. public void insert() {
  91. FileSourceDto expected = new FileSourceDto()
  92. .setProjectUuid("PRJ_UUID")
  93. .setFileUuid("FILE2_UUID")
  94. .setBinaryData("FILE2_BINARY_DATA".getBytes())
  95. .setDataHash("FILE2_DATA_HASH")
  96. .setLineHashes(of("LINE1_HASH", "LINE2_HASH"))
  97. .setSrcHash("FILE2_HASH")
  98. .setCreatedAt(1500000000000L)
  99. .setUpdatedAt(1500000000001L)
  100. .setLineHashesVersion(1)
  101. .setRevision("123456789");
  102. underTest.insert(dbSession, expected);
  103. dbSession.commit();
  104. FileSourceDto fileSourceDto = underTest.selectByFileUuid(dbSession, expected.getFileUuid());
  105. assertThat(fileSourceDto.getProjectUuid()).isEqualTo(expected.getProjectUuid());
  106. assertThat(fileSourceDto.getFileUuid()).isEqualTo(expected.getFileUuid());
  107. assertThat(fileSourceDto.getBinaryData()).isEqualTo(expected.getBinaryData());
  108. assertThat(fileSourceDto.getDataHash()).isEqualTo(expected.getDataHash());
  109. assertThat(fileSourceDto.getRawLineHashes()).isEqualTo(expected.getRawLineHashes());
  110. assertThat(fileSourceDto.getLineHashes()).isEqualTo(expected.getLineHashes());
  111. assertThat(fileSourceDto.getLineCount()).isEqualTo(expected.getLineCount());
  112. assertThat(fileSourceDto.getSrcHash()).isEqualTo(expected.getSrcHash());
  113. assertThat(fileSourceDto.getCreatedAt()).isEqualTo(expected.getCreatedAt());
  114. assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(expected.getUpdatedAt());
  115. assertThat(fileSourceDto.getRevision()).isEqualTo(expected.getRevision());
  116. }
  117. @Test
  118. public void insert_does_not_fail_on_FileSourceDto_with_only_non_nullable_data() {
  119. FileSourceDto fileSourceDto = new FileSourceDto()
  120. .setProjectUuid("Foo")
  121. .setFileUuid("Bar")
  122. .setCreatedAt(1500000000000L)
  123. .setUpdatedAt(1500000000001L);
  124. underTest.insert(dbSession, fileSourceDto);
  125. dbSession.commit();
  126. }
  127. @Test
  128. public void selectSourceByFileUuid_reads_source_without_line_hashes() {
  129. FileSourceDto fileSourceDto = new FileSourceDto()
  130. .setProjectUuid("Foo")
  131. .setFileUuid("Bar")
  132. .setCreatedAt(1500000000000L)
  133. .setUpdatedAt(1500000000001L);
  134. underTest.insert(dbSession, fileSourceDto);
  135. dbSession.commit();
  136. FileSourceDto res = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid());
  137. assertThat(res.getLineCount()).isEqualTo(0);
  138. assertThat(res.getLineHashes()).isEmpty();
  139. }
  140. @Test
  141. public void selectLineHashes_does_not_fail_when_lineshashes_is_null() {
  142. dbTester.prepareDbUnit(getClass(), "shared.xml");
  143. underTest.insert(dbSession, new FileSourceDto()
  144. .setProjectUuid("PRJ_UUID")
  145. .setFileUuid("FILE2_UUID")
  146. .setBinaryData("FILE2_BINARY_DATA".getBytes())
  147. .setDataHash("FILE2_DATA_HASH")
  148. .setSrcHash("FILE2_HASH")
  149. .setCreatedAt(1500000000000L)
  150. .setUpdatedAt(1500000000001L)
  151. .setRevision("123456789"));
  152. dbSession.commit();
  153. assertThat(underTest.selectLineHashes(dbSession, "FILE2_UUID")).isEmpty();
  154. }
  155. @Test
  156. public void selectLineHashesVersion_returns_without_significant_code_by_default() {
  157. underTest.insert(dbSession, new FileSourceDto()
  158. .setProjectUuid("PRJ_UUID")
  159. .setFileUuid("FILE2_UUID")
  160. .setBinaryData("FILE2_BINARY_DATA".getBytes())
  161. .setDataHash("FILE2_DATA_HASH")
  162. .setLineHashes(singletonList("hashes"))
  163. .setSrcHash("FILE2_HASH")
  164. .setCreatedAt(1500000000000L)
  165. .setUpdatedAt(1500000000001L)
  166. .setRevision("123456789"));
  167. dbSession.commit();
  168. assertThat(underTest.selectLineHashesVersion(dbSession, "FILE2_UUID")).isEqualTo(LineHashVersion.WITHOUT_SIGNIFICANT_CODE);
  169. }
  170. @Test
  171. public void selectLineHashesVersion_succeeds() {
  172. underTest.insert(dbSession, new FileSourceDto()
  173. .setProjectUuid("PRJ_UUID")
  174. .setFileUuid("FILE2_UUID")
  175. .setBinaryData("FILE2_BINARY_DATA".getBytes())
  176. .setDataHash("FILE2_DATA_HASH")
  177. .setLineHashes(singletonList("hashes"))
  178. .setSrcHash("FILE2_HASH")
  179. .setCreatedAt(1500000000000L)
  180. .setUpdatedAt(1500000000001L)
  181. .setLineHashesVersion(1)
  182. .setRevision("123456789"));
  183. dbSession.commit();
  184. assertThat(underTest.selectLineHashesVersion(dbSession, "FILE2_UUID")).isEqualTo(LineHashVersion.WITH_SIGNIFICANT_CODE);
  185. }
  186. @Test
  187. public void readLineHashesStream_does_not_fail_when_lineshashes_is_null() {
  188. dbTester.prepareDbUnit(getClass(), "shared.xml");
  189. underTest.insert(dbSession, new FileSourceDto()
  190. .setProjectUuid("PRJ_UUID")
  191. .setFileUuid("FILE2_UUID")
  192. .setBinaryData("FILE2_BINARY_DATA".getBytes())
  193. .setDataHash("FILE2_DATA_HASH")
  194. .setSrcHash("FILE2_HASH")
  195. .setCreatedAt(1500000000000L)
  196. .setUpdatedAt(1500000000001L)
  197. .setRevision("123456789"));
  198. dbSession.commit();
  199. boolean[] flag = {false};
  200. underTest.readLineHashesStream(dbSession, "FILE2_UUID", new Consumer<Reader>() {
  201. @Override
  202. public void accept(@Nullable Reader input) {
  203. fail("function must never been called since there is no data to read");
  204. flag[0] = true;
  205. }
  206. });
  207. assertThat(flag[0]).isFalse();
  208. }
  209. @Test
  210. public void scrollLineHashes_has_no_effect_if_no_uuids() {
  211. underTest.scrollLineHashes(dbSession, emptySet(), resultContext -> fail("handler should not be called"));
  212. }
  213. @Test
  214. public void scrollLineHashes_scrolls_hashes_of_specific_keys() {
  215. OrganizationDto organization = dbTester.organizations().insert();
  216. ComponentDto project = new Random().nextBoolean() ? dbTester.components().insertPrivateProject(organization) : dbTester.components().insertPublicProject(organization);
  217. ComponentDto file1 = dbTester.components().insertComponent(newFileDto(project));
  218. FileSourceDto fileSource1 = dbTester.fileSources().insertFileSource(file1);
  219. ComponentDto file2 = dbTester.components().insertComponent(newFileDto(project));
  220. FileSourceDto fileSource2 = dbTester.fileSources().insertFileSource(file2);
  221. ComponentDto file3 = dbTester.components().insertComponent(newFileDto(project));
  222. FileSourceDto fileSource3 = dbTester.fileSources().insertFileSource(file3);
  223. LineHashesWithKeyDtoHandler handler = scrollLineHashes(file1.uuid());
  224. assertThat(handler.dtos).hasSize(1);
  225. verifyLinesHashes(handler, file1, fileSource1);
  226. handler = scrollLineHashes(file2.uuid());
  227. assertThat(handler.dtos).hasSize(1);
  228. verifyLinesHashes(handler, file2, fileSource2);
  229. handler = scrollLineHashes(file2.uuid(), file1.uuid(), file3.uuid());
  230. assertThat(handler.dtos).hasSize(3);
  231. verifyLinesHashes(handler, file1, fileSource1);
  232. verifyLinesHashes(handler, file2, fileSource2);
  233. verifyLinesHashes(handler, file3, fileSource3);
  234. }
  235. @Test
  236. public void scrollLineHashes_does_not_scroll_hashes_of_component_without_path() {
  237. OrganizationDto organization = dbTester.organizations().insert();
  238. ComponentDto project = new Random().nextBoolean() ? dbTester.components().insertPrivateProject(organization) : dbTester.components().insertPublicProject(organization);
  239. ComponentDto file1 = dbTester.components().insertComponent(newFileDto(project));
  240. FileSourceDto fileSource1 = dbTester.fileSources().insertFileSource(file1);
  241. ComponentDto file2 = dbTester.components().insertComponent(newFileDto(project).setPath(null));
  242. FileSourceDto fileSource2 = dbTester.fileSources().insertFileSource(file2);
  243. LineHashesWithKeyDtoHandler handler = scrollLineHashes(file2.uuid(), file1.uuid());
  244. assertThat(handler.dtos).hasSize(1);
  245. verifyLinesHashes(handler, file1, fileSource1);
  246. }
  247. @Test
  248. public void scrollLineHashes_handles_scrolling_more_than_1000_files() {
  249. OrganizationDto organization = dbTester.organizations().insert();
  250. ComponentDto project = new Random().nextBoolean() ? dbTester.components().insertPrivateProject(organization) : dbTester.components().insertPublicProject(organization);
  251. List<ComponentDto> files = IntStream.range(0, 1001 + new Random().nextInt(5))
  252. .mapToObj(i -> {
  253. ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
  254. dbTester.fileSources().insertFileSource(file);
  255. return file;
  256. })
  257. .collect(Collectors.toList());
  258. LineHashesWithKeyDtoHandler handler = new LineHashesWithKeyDtoHandler();
  259. underTest.scrollLineHashes(dbSession, files.stream().map(ComponentDto::uuid).collect(Collectors.toSet()), handler);
  260. assertThat(handler.dtos).hasSize(files.size());
  261. files.forEach(t -> assertThat(handler.getByUuid(t.uuid())).isPresent());
  262. }
  263. private LineHashesWithKeyDtoHandler scrollLineHashes(String... uuids) {
  264. LineHashesWithKeyDtoHandler handler = new LineHashesWithKeyDtoHandler();
  265. underTest.scrollLineHashes(dbSession, ImmutableSet.copyOf(uuids), handler);
  266. return handler;
  267. }
  268. private static void verifyLinesHashes(LineHashesWithKeyDtoHandler handler, ComponentDto file, FileSourceDto fileSource) {
  269. LineHashesWithUuidDto dto = handler.getByUuid(file.uuid()).get();
  270. assertThat(dto.getPath()).isEqualTo(file.path());
  271. assertThat(dto.getRawLineHashes()).isEqualTo(fileSource.getRawLineHashes());
  272. assertThat(dto.getLineHashes()).isEqualTo(fileSource.getLineHashes());
  273. }
  274. private static final class LineHashesWithKeyDtoHandler implements ResultHandler<LineHashesWithUuidDto> {
  275. private final List<LineHashesWithUuidDto> dtos = new ArrayList<>();
  276. @Override
  277. public void handleResult(ResultContext<? extends LineHashesWithUuidDto> resultContext) {
  278. dtos.add(resultContext.getResultObject());
  279. }
  280. public Optional<LineHashesWithUuidDto> getByUuid(String uuid) {
  281. return dtos.stream()
  282. .filter(t -> uuid.equals(t.getUuid()))
  283. .findAny();
  284. }
  285. }
  286. @Test
  287. public void update() {
  288. dbTester.prepareDbUnit(getClass(), "shared.xml");
  289. underTest.update(dbSession, new FileSourceDto()
  290. .setId(101L)
  291. .setProjectUuid("PRJ_UUID")
  292. .setFileUuid("FILE1_UUID")
  293. .setBinaryData("updated data".getBytes())
  294. .setDataHash("NEW_DATA_HASH")
  295. .setSrcHash("NEW_FILE_HASH")
  296. .setLineHashes(singletonList("NEW_LINE_HASHES"))
  297. .setUpdatedAt(1500000000002L)
  298. .setLineHashesVersion(1)
  299. .setRevision("987654321"));
  300. dbSession.commit();
  301. dbTester.assertDbUnitTable(getClass(), "update-result.xml", "file_sources", "project_uuid", "file_uuid",
  302. "data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "revision", "line_hashes_version");
  303. }
  304. @Test
  305. public void update_to_no_line_hashes() {
  306. ImmutableList<String> lineHashes = of("a", "b", "c");
  307. FileSourceDto fileSourceDto = new FileSourceDto()
  308. .setProjectUuid("Foo")
  309. .setFileUuid("Bar")
  310. .setLineHashes(lineHashes)
  311. .setCreatedAt(1500000000000L)
  312. .setUpdatedAt(1500000000001L);
  313. underTest.insert(dbSession, fileSourceDto);
  314. dbSession.commit();
  315. FileSourceDto resBefore = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid());
  316. assertThat(resBefore.getLineCount()).isEqualTo(lineHashes.size());
  317. assertThat(resBefore.getLineHashes()).isEqualTo(lineHashes);
  318. fileSourceDto.setId(resBefore.getId());
  319. fileSourceDto.setLineHashes(emptyList());
  320. underTest.update(dbSession, fileSourceDto);
  321. dbSession.commit();
  322. FileSourceDto res = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid());
  323. assertThat(res.getLineHashes()).isEmpty();
  324. assertThat(res.getLineCount()).isEqualTo(1);
  325. }
  326. private static class ReaderToStringConsumer implements Consumer<Reader> {
  327. String result = null;
  328. @Override
  329. public void accept(Reader input) {
  330. try {
  331. result = IOUtils.toString(input);
  332. } catch (IOException e) {
  333. throw new RuntimeException(e);
  334. }
  335. }
  336. }
  337. }