@Test public void diffFile() throws Exception { doAnswer(invocation -> { final AsyncMethodCallback<DiffFileResult> callback = invocation.getArgument(5); callback.onComplete(new DiffFileResult(ChangeType.UPSERT_TEXT, "some_text")); return null; }).when(iface).diffFile(any(), any(), any(), any(), any(), any()); assertThat(client.getDiff("project", "repo", new Revision(1), new Revision(3), Query.ofText("/a.txt")).get()) .isEqualTo(Change.ofTextUpsert("/a.txt", "some_text")); verify(iface).diffFile(eq("project"), eq("repo"), any(), any(), any(), any()); }
@Override protected void scaffold(CentralDogma client) { client.createProject(PROJ).join(); client.createRepository(PROJ, REPO).join(); client.push(PROJ, REPO, Revision.HEAD, "Create a large file.", Change.ofTextUpsert(PATH, CONTENT)).join(); } };
@Test public void getPreviewDiffs() throws Exception { doAnswer(invocation -> { final AsyncMethodCallback<List<TChange>> callback = invocation.getArgument(4); final TChange change = new TChange("/a.txt", ChangeType.UPSERT_TEXT); change.setContent("content"); callback.onComplete(ImmutableList.of(change)); return null; }).when(iface).getPreviewDiffs(any(), any(), any(), any(), any()); assertThat(client.getPreviewDiffs("project", "repo", new Revision(1), ImmutableList.of(Change.ofTextUpsert("/a.txt", "content"))).get()) .isEqualTo(ImmutableList.of(Change.ofTextUpsert("/a.txt", "content"))); verify(iface).getPreviewDiffs(eq("project"), eq("repo"), any(), any(), any()); }
@Test public void getDiffs() throws Exception { doAnswer(invocation -> { final AsyncMethodCallback<List<TChange>> callback = invocation.getArgument(5); final TChange change = new TChange("/a.txt", ChangeType.UPSERT_TEXT); change.setContent("content"); callback.onComplete(ImmutableList.of(change)); return null; }).when(iface).getDiffs(any(), any(), any(), any(), any(), any()); assertThat(client.getDiffs("project", "repo", new Revision(1), new Revision(3), "path").get()) .isEqualTo(ImmutableList.of(Change.ofTextUpsert("/a.txt", "content"))); verify(iface).getDiffs(eq("project"), eq("repo"), any(), any(), eq("path"), any()); }
private static Entry<CommitMessageDto, Change<?>> commitMessageAndChange(AggregatedHttpMessage message) { try { final JsonNode node = Jackson.readTree(message.content().toStringUtf8()); final CommitMessageDto commitMessage = Jackson.convertValue(node.get("commitMessage"), CommitMessageDto.class); final EntryDto file = Jackson.convertValue(node.get("file"), EntryDto.class); final Change<?> change; switch (file.getType()) { case "JSON": change = Change.ofJsonUpsert(file.getPath(), file.getContent()); break; case "TEXT": change = Change.ofTextUpsert(file.getPath(), file.getContent()); break; default: throw new IllegalArgumentException("unsupported file type: " + file.getType()); } return Maps.immutableEntry(commitMessage, change); } catch (IOException e) { throw new IllegalArgumentException("invalid data to be parsed", e); } }
@Override protected void scaffold(CentralDogma client) { client.createProject("directory").join(); client.createRepository("directory", "my-service").join(); client.push("directory", "my-service", Revision.HEAD, "commit", Change.ofJsonUpsert("/endpoint.json", HOST_AND_PORT_LIST_JSON)) .join(); client.push("directory", "my-service", Revision.HEAD, "commit", Change.ofTextUpsert("/endpoints.txt", String.join("\n", HOST_AND_PORT_LIST))) .join(); } };
private static Entry<CommitMessageDto, Change<?>> commitMessageAndChange(AggregatedHttpMessage message) { try { final JsonNode node = Jackson.readTree(message.content().toStringUtf8()); final CommitMessageDto commitMessage = Jackson.convertValue(node.get("commitMessage"), CommitMessageDto.class); final EntryDto file = Jackson.convertValue(node.get("file"), EntryDto.class); final Change<?> change; switch (file.getType()) { case "JSON": change = Change.ofJsonUpsert(file.getPath(), file.getContent()); break; case "TEXT": change = Change.ofTextUpsert(file.getPath(), file.getContent()); break; default: throw new IllegalArgumentException("unsupported file type: " + file.getType()); } return Maps.immutableEntry(commitMessage, change); } catch (IOException e) { throw new IllegalArgumentException("invalid data to be parsed", e); } }
private static Entry<CommitMessageDto, Change<?>> commitMessageAndChange(AggregatedHttpMessage message) { try { final JsonNode node = Jackson.readTree(message.content().toStringUtf8()); final CommitMessageDto commitMessage = Jackson.convertValue(node.get("commitMessage"), CommitMessageDto.class); final EntryDto file = Jackson.convertValue(node.get("file"), EntryDto.class); final Change<?> change; switch (file.getType()) { case "JSON": change = Change.ofJsonUpsert(file.getPath(), file.getContent()); break; case "TEXT": change = Change.ofTextUpsert(file.getPath(), file.getContent()); break; default: throw new IllegalArgumentException("unsupported file type: " + file.getType()); } return Maps.immutableEntry(commitMessage, change); } catch (IOException e) { throw new IllegalArgumentException("invalid data to be parsed", e); } }
@Test public void push() throws Exception { doAnswer(invocation -> { final AsyncMethodCallback<TCommit> callback = invocation.getArgument(7); callback.onComplete(new TCommit( new TRevision(1), new TAuthor("name", "name@sample.com"), TIMESTAMP, "summary", new Comment("detail"), ImmutableList.of())); return null; }).when(iface).push(anyString(), anyString(), any(), any(), any(), any(), any(), any()); assertThat(client.push("project", "repo", new Revision(1), new Author("name", "name@sample.com"), "summary", "detail", Markup.PLAINTEXT, ImmutableList.of(Change.ofTextUpsert("/a.txt", "hello")) ).get()).isEqualTo(new PushResult(new Revision(1), Instant.parse(TIMESTAMP).toEpochMilli())); verify(iface).push(eq("project"), eq("repo"), any(), any(), eq("summary"), any(), any(), any()); }
@Test public void testEmptyCommitWithRedundantUpsert2() throws Exception { // Create files to produce redundant changes. final Change<JsonNode> change1 = Change.ofJsonUpsert("/redundant_upsert_2.json", "{ \"foo\": 0, \"bar\": 1 }"); final Change<String> change2 = Change.ofTextUpsert("/redundant_upsert_2.txt", "foo"); repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, change1).join(); repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, change2).join(); // Ensure redundant changes do not count as a valid change. assertThatThrownBy(() -> repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, change1).join()) .isInstanceOf(CompletionException.class) .hasCauseInstanceOf(RedundantChangeException.class); assertThatThrownBy(() -> repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, change2).join()) .isInstanceOf(CompletionException.class) .hasCauseInstanceOf(RedundantChangeException.class); // Ensure a change only whose serialized form is different does not count. final Change<JsonNode> change1a = Change.ofJsonUpsert("/redundant_upsert_2.json", "{ \"bar\": 1, \"foo\": 0 }"); assertThatThrownBy(() -> repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, change1a).join()) .isInstanceOf(CompletionException.class) .hasCauseInstanceOf(RedundantChangeException.class); }
@Test public void singleDiff() { final Repository repo = setMockNames(newCachingRepo()); final Query<String> query = Query.ofText("/foo.txt"); final Change<String> change = Change.ofTextUpsert(query.path(), "bar"); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(HEAD, INIT); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(new Revision(10), INIT); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(new Revision(-1), new Revision(-10)); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(new Revision(10), new Revision(-10)); // Uncached when(delegateRepo.diff(any(), any(), any(Query.class))).thenReturn(completedFuture(change)); assertThat(repo.diff(HEAD, INIT, query).join()).isEqualTo(change); verify(delegateRepo).diff(INIT, new Revision(10), query); verifyNoMoreInteractions(delegateRepo); // Cached clearInvocations(delegateRepo); assertThat(repo.diff(HEAD, new Revision(-10), query).join()).isEqualTo(change); assertThat(repo.diff(HEAD, INIT, query).join()).isEqualTo(change); assertThat(repo.diff(new Revision(10), new Revision(-10), query).join()).isEqualTo(change); assertThat(repo.diff(new Revision(10), INIT, query).join()).isEqualTo(change); verify(delegateRepo, never()).diff(any(), any(), any(Query.class)); verifyNoMoreInteractions(delegateRepo); }
@Test public void operationOnClosedRepository() throws Exception { final CentralDogmaException expectedException = new CentralDogmaException(); final GitRepository repo = new GitRepository(mock(Project.class), new File(repoDir.getRoot(), "close_test_repo"), commonPool(), 0L, Author.SYSTEM); repo.close(() -> expectedException); assertThatThrownBy(() -> repo.find(INIT, "/**").join()).hasCause(expectedException); assertThatThrownBy(() -> repo.history(INIT, HEAD, "/**").join()).hasCause(expectedException); assertThatThrownBy(() -> repo.diff(INIT, HEAD, "/**").join()).hasCause(expectedException); assertThatThrownBy(() -> repo.previewDiff( INIT, Change.ofTextUpsert("/foo.txt", "foo")).join()).hasCause(expectedException); assertThatThrownBy(() -> repo.commit( INIT, 0, Author.SYSTEM, "foo", Change.ofTextUpsert("/foo", "foo")).join()).hasCause(expectedException); assertThatThrownBy(() -> repo.watch( INIT, "/**").get(10, TimeUnit.SECONDS)).hasCause(expectedException); assertThatThrownBy(() -> repo.watch( INIT, Query.ofJson("/foo.json")).get(10, TimeUnit.SECONDS)).hasCause(expectedException); } }
@Test public void multiDiff() { final Repository repo = setMockNames(newCachingRepo()); final Map<String, Change<?>> changes = ImmutableMap.of( "/foo.txt", Change.ofTextUpsert("/foo.txt", "bar")); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(HEAD, INIT); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(new Revision(10), INIT); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(new Revision(-1), new Revision(-10)); doReturn(new RevisionRange(10, 1)).when(delegateRepo).normalizeNow(new Revision(10), new Revision(-10)); // Uncached when(delegateRepo.diff(any(), any(), any(String.class))).thenReturn(completedFuture(changes)); assertThat(repo.diff(HEAD, INIT, "/**").join()).isEqualTo(changes); verify(delegateRepo).diff(INIT, new Revision(10), "/**"); verifyNoMoreInteractions(delegateRepo); // Cached clearInvocations(delegateRepo); assertThat(repo.diff(HEAD, new Revision(-10), "/**").join()).isEqualTo(changes); assertThat(repo.diff(HEAD, INIT, "/**").join()).isEqualTo(changes); assertThat(repo.diff(new Revision(10), new Revision(-10), "/**").join()).isEqualTo(changes); assertThat(repo.diff(new Revision(10), INIT, "/**").join()).isEqualTo(changes); verify(delegateRepo, never()).diff(any(), any(), any(Query.class)); verifyNoMoreInteractions(delegateRepo); }
@Test public void testInvalidRevision() throws Exception { final Change<String> change = Change.ofTextUpsert("/a_new_text_file.txt", "text"); assertThatThrownByWithExpectedException(RevisionNotFoundException.class, "2147483647", () -> rule.client().getPreviewDiffs( rule.project(), rule.repo1(), new Revision(Integer.MAX_VALUE), change).join()) .isInstanceOf(CompletionException.class).hasCauseInstanceOf(RevisionNotFoundException.class); }
@Test public void testDiff_rename() throws Exception { final CentralDogma client = rule.client(); final Revision rev1 = client.push(rule.project(), rule.repo1(), HEAD, "summary1", Change.ofTextUpsert("/bar.txt", "hello")).join().revision(); final Revision rev2 = client.push(rule.project(), rule.repo1(), HEAD, "summary2", Change.ofRename("/bar.txt", "/baz.txt")).join().revision(); assertThat(rev1.forward(1)).isEqualTo(rev2); assertThat(client.getDiff(rule.project(), rule.repo1(), rev1, rev2, Query.ofText("/bar.txt")).join()) .isEqualTo(Change.ofRemoval("/bar.txt")); } }
@Test public void testDiff_remove() throws Exception { final CentralDogma client = rule.client(); final Revision rev1 = client.push(rule.project(), rule.repo1(), HEAD, "summary1", Change.ofTextUpsert("/foo.txt", "hello")).join().revision(); final Revision rev2 = client.push(rule.project(), rule.repo1(), HEAD, "summary2", Change.ofRemoval("/foo.txt")).join().revision(); assertThat(rev1.forward(1)).isEqualTo(rev2); assertThat(client.getDiff(rule.project(), rule.repo1(), rev1, rev1, Query.ofText("/foo.txt")).join().type()) .isEqualTo(ChangeType.APPLY_TEXT_PATCH); assertThat(client.getDiff(rule.project(), rule.repo1(), rev1, rev2, Query.ofText("/foo.txt")).join()) .isEqualTo(Change.ofRemoval("/foo.txt")); }
@Test(timeout = 10000) public void text() throws Exception { try (Watcher<String> watcher = dogma.client().fileWatcher("directory", "my-service", Query.ofText("/endpoints.txt"))) { final CountDownLatch latch = new CountDownLatch(2); watcher.watch(unused -> latch.countDown()); final CentralDogmaEndpointGroup<String> endpointGroup = CentralDogmaEndpointGroup.ofWatcher( watcher, EndpointListDecoder.TEXT); endpointGroup.awaitInitialEndpoints(); assertThat(endpointGroup.endpoints()).isEqualTo(ENDPOINT_LIST); assertThat(latch.getCount()).isOne(); dogma.client().push("directory", "my-service", Revision.HEAD, "commit", Change.ofTextUpsert("/endpoints.txt", "foo.bar:1234")) .join(); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> assertThat(latch.getCount()).isZero()); assertThat(endpointGroup.endpoints()).containsExactly(Endpoint.of("foo.bar", 1234)); } } }
@Override protected com.linecorp.centraldogma.common.Change<?> doBackward(Change c) { switch (c.getType()) { case UPSERT_JSON: return com.linecorp.centraldogma.common.Change.ofJsonUpsert(c.getPath(), c.getContent()); case UPSERT_TEXT: return com.linecorp.centraldogma.common.Change.ofTextUpsert(c.getPath(), c.getContent()); case REMOVE: return com.linecorp.centraldogma.common.Change.ofRemoval(c.getPath()); case RENAME: return com.linecorp.centraldogma.common.Change.ofRename(c.getPath(), c.getContent()); case APPLY_JSON_PATCH: return com.linecorp.centraldogma.common.Change.ofJsonPatch(c.getPath(), c.getContent()); case APPLY_TEXT_PATCH: return com.linecorp.centraldogma.common.Change.ofTextPatch(c.getPath(), c.getContent()); } throw new Error(); }
@Override protected com.linecorp.centraldogma.common.Change<?> doBackward(Change c) { switch (c.getType()) { case UPSERT_JSON: return com.linecorp.centraldogma.common.Change.ofJsonUpsert(c.getPath(), c.getContent()); case UPSERT_TEXT: return com.linecorp.centraldogma.common.Change.ofTextUpsert(c.getPath(), c.getContent()); case REMOVE: return com.linecorp.centraldogma.common.Change.ofRemoval(c.getPath()); case RENAME: return com.linecorp.centraldogma.common.Change.ofRename(c.getPath(), c.getContent()); case APPLY_JSON_PATCH: return com.linecorp.centraldogma.common.Change.ofJsonPatch(c.getPath(), c.getContent()); case APPLY_TEXT_PATCH: return com.linecorp.centraldogma.common.Change.ofTextPatch(c.getPath(), c.getContent()); } throw new Error(); }
@Before public void setUp() throws Exception { prefix = '/' + testName.getMethodName() + '/'; allPattern = prefix + "**"; for (int i = 0; i < NUM_ITERATIONS; i++) { final String jsonPath = prefix + i + ".json"; final String textPath = prefix + i + ".txt"; jsonPaths[i] = jsonPath; textPaths[i] = textPath; jsonUpserts[i] = Change.ofJsonUpsert(jsonPath, "{ \"" + i + "\": " + i + " }"); textUpserts[i] = Change.ofTextUpsert(textPath, "value:\n" + i); } jsonPatches[0] = Change.ofJsonPatch(jsonPaths[0], null, jsonUpserts[0].content()); textPatches[0] = Change.ofTextPatch(textPaths[0], null, textUpserts[0].content()); for (int i = 1; i < NUM_ITERATIONS; i++) { jsonPatches[i] = Change.ofJsonPatch(jsonPaths[0], jsonUpserts[i - 1].content(), jsonUpserts[i].content()); textPatches[i] = Change.ofTextPatch(textPaths[0], textUpserts[i - 1].content(), textUpserts[i].content()); } watchConsumer = null; }