| // Copyright (C) 2014 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.google.gerrit.server.change; |
| |
| import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel; |
| import static com.google.gerrit.entities.Permission.forLabel; |
| import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS; |
| import static com.google.gerrit.server.project.testing.TestLabels.label; |
| import static com.google.gerrit.server.project.testing.TestLabels.value; |
| import static org.junit.Assert.assertEquals; |
| |
| import com.google.common.collect.ImmutableSet; |
| import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; |
| import com.google.gerrit.entities.AccessSection; |
| import com.google.gerrit.entities.Account; |
| import com.google.gerrit.entities.Change; |
| import com.google.gerrit.entities.LabelId; |
| import com.google.gerrit.entities.LabelType; |
| import com.google.gerrit.entities.PatchSetApproval; |
| import com.google.gerrit.extensions.api.GerritApi; |
| import com.google.gerrit.extensions.common.ChangeInfo; |
| import com.google.gerrit.extensions.common.ChangeInput; |
| import com.google.gerrit.lifecycle.LifecycleManager; |
| import com.google.gerrit.server.IdentifiedUser; |
| import com.google.gerrit.server.account.AccountManager; |
| import com.google.gerrit.server.account.AuthRequest; |
| import com.google.gerrit.server.change.LabelNormalizer.Result; |
| import com.google.gerrit.server.config.AllProjectsName; |
| import com.google.gerrit.server.git.GitRepositoryManager; |
| import com.google.gerrit.server.git.meta.MetaDataUpdate; |
| import com.google.gerrit.server.notedb.ChangeNotes; |
| import com.google.gerrit.server.project.ProjectCache; |
| import com.google.gerrit.server.project.ProjectConfig; |
| import com.google.gerrit.server.schema.SchemaCreator; |
| import com.google.gerrit.server.util.ThreadLocalRequestContext; |
| import com.google.gerrit.server.util.time.TimeUtil; |
| import com.google.gerrit.testing.InMemoryModule; |
| import com.google.inject.Guice; |
| import com.google.inject.Inject; |
| import com.google.inject.Injector; |
| import org.eclipse.jgit.lib.Repository; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| /** Unit tests for {@link LabelNormalizer}. */ |
| public class LabelNormalizerTest { |
| @Inject private AccountManager accountManager; |
| @Inject private AllProjectsName allProjects; |
| @Inject private GitRepositoryManager repoManager; |
| @Inject private IdentifiedUser.GenericFactory userFactory; |
| @Inject private LabelNormalizer norm; |
| @Inject private MetaDataUpdate.User metaDataUpdateFactory; |
| @Inject private ProjectCache projectCache; |
| @Inject private SchemaCreator schemaCreator; |
| @Inject protected ThreadLocalRequestContext requestContext; |
| @Inject private ChangeNotes.Factory changeNotesFactory; |
| @Inject private ProjectConfig.Factory projectConfigFactory; |
| @Inject private GerritApi gApi; |
| @Inject private ProjectOperations projectOperations; |
| @Inject private AuthRequest.Factory authRequestFactory; |
| |
| private LifecycleManager lifecycle; |
| private Account.Id userId; |
| private IdentifiedUser user; |
| private Change change; |
| private ChangeNotes notes; |
| |
| @Before |
| public void setUpInjector() throws Exception { |
| Injector injector = Guice.createInjector(new InMemoryModule()); |
| injector.injectMembers(this); |
| lifecycle = new LifecycleManager(); |
| lifecycle.add(injector); |
| lifecycle.start(); |
| |
| schemaCreator.create(); |
| userId = accountManager.authenticate(authRequestFactory.createForUser("user")).getAccountId(); |
| user = userFactory.create(userId); |
| |
| requestContext.setContext(() -> user); |
| |
| configureProject(); |
| setUpChange(); |
| } |
| |
| private void configureProject() throws Exception { |
| ProjectConfig pc = loadAllProjects(); |
| |
| for (AccessSection sec : pc.getAccessSections()) { |
| pc.upsertAccessSection( |
| sec.getName(), |
| updatedSection -> { |
| for (String label : pc.getLabelSections().keySet()) { |
| updatedSection.removePermission(forLabel(label)); |
| } |
| }); |
| } |
| LabelType lt = |
| label( |
| LabelId.VERIFIED, value(1, LabelId.VERIFIED), value(0, "No score"), value(-1, "Fails")); |
| pc.upsertLabelType(lt); |
| save(pc); |
| } |
| |
| private void setUpChange() throws Exception { |
| ChangeInput input = new ChangeInput(); |
| input.project = allProjects.get(); |
| input.branch = "master"; |
| input.newBranch = true; |
| input.subject = "Test change"; |
| ChangeInfo info = gApi.changes().create(input).get(); |
| notes = changeNotesFactory.createChecked(allProjects, Change.id(info._number)); |
| change = notes.getChange(); |
| } |
| |
| @After |
| public void tearDown() { |
| if (lifecycle != null) { |
| lifecycle.stop(); |
| } |
| requestContext.setContext(null); |
| } |
| |
| @Test |
| public void noNormalizeByPermission() throws Exception { |
| projectOperations |
| .allProjectsForUpdate() |
| .add( |
| allowLabel(LabelId.CODE_REVIEW) |
| .ref("refs/heads/*") |
| .group(REGISTERED_USERS) |
| .range(-1, 1)) |
| .add(allowLabel(LabelId.VERIFIED).ref("refs/heads/*").group(REGISTERED_USERS).range(-1, 1)) |
| .update(); |
| |
| PatchSetApproval cr = psa(userId, LabelId.CODE_REVIEW, 2); |
| PatchSetApproval v = psa(userId, LabelId.VERIFIED, 1); |
| assertEquals(Result.create(set(cr, v), set(), set()), norm.normalize(notes, set(cr, v))); |
| } |
| |
| @Test |
| public void normalizeByType() throws Exception { |
| projectOperations |
| .allProjectsForUpdate() |
| .add( |
| allowLabel(LabelId.CODE_REVIEW) |
| .ref("refs/heads/*") |
| .group(REGISTERED_USERS) |
| .range(-5, 5)) |
| .add(allowLabel(LabelId.VERIFIED).ref("refs/heads/*").group(REGISTERED_USERS).range(-5, 5)) |
| .update(); |
| |
| PatchSetApproval cr = psa(userId, LabelId.CODE_REVIEW, 5); |
| PatchSetApproval v = psa(userId, LabelId.VERIFIED, 5); |
| assertEquals( |
| Result.create(set(), set(copy(cr, 2), copy(v, 1)), set()), |
| norm.normalize(notes, set(cr, v))); |
| } |
| |
| @Test |
| public void emptyPermissionRangeKeepsResult() throws Exception { |
| PatchSetApproval cr = psa(userId, LabelId.CODE_REVIEW, 1); |
| PatchSetApproval v = psa(userId, LabelId.VERIFIED, 1); |
| assertEquals(Result.create(set(cr, v), set(), set()), norm.normalize(notes, set(cr, v))); |
| } |
| |
| @Test |
| public void explicitZeroVoteOnNonEmptyRangeIsPresent() throws Exception { |
| projectOperations |
| .allProjectsForUpdate() |
| .add( |
| allowLabel(LabelId.CODE_REVIEW) |
| .ref("refs/heads/*") |
| .group(REGISTERED_USERS) |
| .range(-1, 1)) |
| .update(); |
| |
| PatchSetApproval cr = psa(userId, LabelId.CODE_REVIEW, 0); |
| PatchSetApproval v = psa(userId, LabelId.VERIFIED, 0); |
| assertEquals(Result.create(set(cr, v), set(), set()), norm.normalize(notes, set(cr, v))); |
| } |
| |
| private ProjectConfig loadAllProjects() throws Exception { |
| try (Repository repo = repoManager.openRepository(allProjects)) { |
| ProjectConfig pc = projectConfigFactory.create(allProjects); |
| pc.load(repo); |
| return pc; |
| } |
| } |
| |
| private void save(ProjectConfig pc) throws Exception { |
| try (MetaDataUpdate md = metaDataUpdateFactory.create(pc.getProject().getNameKey(), user)) { |
| pc.commit(md); |
| projectCache.evictAndReindex(pc.getProject().getNameKey()); |
| } |
| } |
| |
| private PatchSetApproval psa(Account.Id accountId, String label, int value) { |
| return PatchSetApproval.builder() |
| .key(PatchSetApproval.key(change.currentPatchSetId(), accountId, LabelId.create(label))) |
| .value(value) |
| .granted(TimeUtil.now()) |
| .build(); |
| } |
| |
| private PatchSetApproval copy(PatchSetApproval src, int newValue) { |
| return src.toBuilder().value(newValue).build(); |
| } |
| |
| private static ImmutableSet<PatchSetApproval> set(PatchSetApproval... psas) { |
| return ImmutableSet.copyOf(psas); |
| } |
| } |