blob: c1c9444dcb82f4862d16c377d55011a4f448af00 [file] [log] [blame]
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you 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 org.apache.sling.cli.impl.release;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.mail.internet.InternetAddress;
import org.apache.sling.cli.impl.Command;
import org.apache.sling.cli.impl.Credentials;
import org.apache.sling.cli.impl.CredentialsService;
import org.apache.sling.cli.impl.DateProvider;
import org.apache.sling.cli.impl.ExecutionMode;
import org.apache.sling.cli.impl.mail.Email;
import org.apache.sling.cli.impl.mail.Mailer;
import org.apache.sling.cli.impl.mail.VoteThreadFinder;
import org.apache.sling.cli.impl.nexus.StagingRepository;
import org.apache.sling.cli.impl.nexus.RepositoryService;
import org.apache.sling.cli.impl.people.Member;
import org.apache.sling.cli.impl.people.MembersFinder;
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.osgi.framework.ServiceReference;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({
// https://github.com/powermock/powermock/issues/864
"com.sun.org.apache.xerces.*",
"javax.xml.*",
"org.w3c.dom.*"
})
public class TallyVotesCommandTest {
@Before
public void beforeClass() {
DateProvider dateProvider = mock(DateProvider.class);
when(dateProvider.getCurrentDateForEmailHeader()).thenReturn("Thu, 1 Jan 1970 01:00:00 +0100");
osgiContext.registerService(DateProvider.class, dateProvider);
}
@Rule
public final OsgiContext osgiContext = new OsgiContext();
@Test
@PrepareForTest({LoggerFactory.class})
public void testDryRun() throws Exception {
mockStatic(LoggerFactory.class);
Logger logger = mock(Logger.class);
when(LoggerFactory.getLogger(TallyVotesCommand.class)).thenReturn(logger);
List<Email> thread = new ArrayList<>(){{
add(mockEmail("johndoe@apache.org", "John Doe"));
add(mockEmail("alice@apache.org", "Alice"));
add(mockEmail("bob@apache.org", "Bob"));
add(mockEmail("charlie@apache.org", "Charlie"));
add(mockEmail("daniel@apache.org", "Daniel"));
add(mockEmail("johndoe@apache.org", "John Doe"));
}};
prepareExecution(mock(Mailer.class), thread);
TallyVotesCommand tallyVotesCommand = spy(new TallyVotesCommand());
ReusableCLIOptions reusableCLIOptions = mock(ReusableCLIOptions.class);
Whitebox.setInternalState(reusableCLIOptions, "executionMode", ExecutionMode.DRY_RUN);
Whitebox.setInternalState(tallyVotesCommand, "repositoryId", 123);
Whitebox.setInternalState(tallyVotesCommand, "reusableCLIOptions", reusableCLIOptions);
osgiContext.registerInjectActivateService(tallyVotesCommand);
ServiceReference<?> reference =
osgiContext.bundleContext().getServiceReference(Command.class.getName());
Command command = (Command) osgiContext.bundleContext().getService(reference);
command.run();
verify(logger).info(
"From: John Doe <johndoe@apache.org>\n" +
"To: \"Sling Developers List\" <dev@sling.apache.org>\n" +
"Reply-To: \"Sling Developers List\" <dev@sling.apache.org>\n" +
"Date: Thu, 1 Jan 1970 01:00:00 +0100\n" +
"Subject: [RESULT] [VOTE] Release Apache Sling CLI Test 1.0.0\n" +
"\n" +
"Hi,\n" +
"\n" +
"The vote has passed with the following result:\n" +
"\n" +
"+1 (binding): Alice, Bob, Charlie, John Doe\n" +
"+1 (non-binding): Daniel\n" +
"\n" +
"I will copy this release to the Sling dist directory and\n" +
"promote the artifacts to the central Maven repository.\n" +
"\n" +
"Regards,\n" +
"John Doe\n"
);
}
@Test
@PrepareForTest({LoggerFactory.class})
public void testDryRunNotEnoughBindingVotes() throws Exception {
mockStatic(LoggerFactory.class);
Logger logger = mock(Logger.class);
when(LoggerFactory.getLogger(TallyVotesCommand.class)).thenReturn(logger);
List<Email> thread = new ArrayList<>(){{
add(mockEmail("johndoe@apache.org", "John Doe"));
add(mockEmail("alice@apache.org", "Alice"));
add(mockEmail("bob@apache.org", "Bob"));
add(mockEmail("daniel@apache.org", "Daniel"));
}};
prepareExecution(mock(Mailer.class), thread);
TallyVotesCommand tallyVotesCommand = spy(new TallyVotesCommand());
ReusableCLIOptions reusableCLIOptions = mock(ReusableCLIOptions.class);
Whitebox.setInternalState(reusableCLIOptions, "executionMode", ExecutionMode.DRY_RUN);
Whitebox.setInternalState(tallyVotesCommand, "repositoryId", 123);
Whitebox.setInternalState(tallyVotesCommand, "reusableCLIOptions", reusableCLIOptions);
osgiContext.registerInjectActivateService(tallyVotesCommand);
ServiceReference<?> reference =
osgiContext.bundleContext().getServiceReference(Command.class.getName());
Command command = (Command) osgiContext.bundleContext().getService(reference);
command.run();
verify(logger).info(
"Release {} does not have at least 3 binding votes.",
"Apache Sling CLI Test 1.0.0"
);
}
@Test
public void testAuto() throws Exception {
List<Email> thread = new ArrayList<>(){{
add(mockEmail("johndoe@apache.org", "John Doe"));
add(mockEmail("alice@apache.org", "Alice"));
add(mockEmail("bob@apache.org", "Bob"));
add(mockEmail("charlie@apache.org", "Charlie"));
add(mockEmail("daniel@apache.org", "Daniel"));
add(mockEmail("johndoe@apache.org", "John Doe"));
}};
Mailer mailer = mock(Mailer.class);
prepareExecution(mailer, thread);
TallyVotesCommand tallyVotesCommand = spy(new TallyVotesCommand());
ReusableCLIOptions reusableCLIOptions = mock(ReusableCLIOptions.class);
Whitebox.setInternalState(reusableCLIOptions, "executionMode", ExecutionMode.AUTO);
Whitebox.setInternalState(tallyVotesCommand, "repositoryId", 123);
Whitebox.setInternalState(tallyVotesCommand, "reusableCLIOptions", reusableCLIOptions);
osgiContext.registerInjectActivateService(tallyVotesCommand);
ServiceReference<?> reference =
osgiContext.bundleContext().getServiceReference(Command.class.getName());
Command command = (Command) osgiContext.bundleContext().getService(reference);
command.run();
verify(mailer).send(
"From: John Doe <johndoe@apache.org>\n" +
"To: \"Sling Developers List\" <dev@sling.apache.org>\n" +
"Reply-To: \"Sling Developers List\" <dev@sling.apache.org>\n" +
"Date: Thu, 1 Jan 1970 01:00:00 +0100\n" +
"Subject: [RESULT] [VOTE] Release Apache Sling CLI Test 1.0.0\n" +
"\n" +
"Hi,\n" +
"\n" +
"The vote has passed with the following result:\n" +
"\n" +
"+1 (binding): Alice, Bob, Charlie, John Doe\n" +
"+1 (non-binding): Daniel\n" +
"\n" +
"I will copy this release to the Sling dist directory and\n" +
"promote the artifacts to the central Maven repository.\n" +
"\n" +
"Regards,\n" +
"John Doe\n"
);
}
private Email mockEmail(String address, String name) throws Exception {
Email email = mock(Email.class);
when(email.getBody()).thenReturn("+1");
when(email.getFrom()).thenReturn(new InternetAddress(address, name));
return email;
}
private void prepareExecution(Mailer mailer, List<Email> thread) throws IOException {
CredentialsService credentialsService = mock(CredentialsService.class);
when(credentialsService.getAsfCredentials()).thenReturn(new Credentials("johndoe", "secret"));
MembersFinder membersFinder = spy(new MembersFinder());
Set<Member> members = new HashSet<>(){{
add(new Member("johndoe", "John Doe", true));
add(new Member("alice", "Alice", true));
add(new Member("bob", "Bob", true));
add(new Member("charlie", "Charlie", true));
add(new Member("daniel", "Daniel", false));
}};
Whitebox.setInternalState(membersFinder, "members", members);
Whitebox.setInternalState(membersFinder, "lastCheck", System.currentTimeMillis());
StagingRepository stagingRepository = mock(StagingRepository.class);
when(stagingRepository.getDescription()).thenReturn("Apache Sling CLI Test 1.0.0");
RepositoryService repositoryService = mock(RepositoryService.class);
when(repositoryService.find(123)).thenReturn(stagingRepository);
VoteThreadFinder voteThreadFinder = mock(VoteThreadFinder.class);
when(voteThreadFinder.findVoteThread("CLI Test 1.0.0")).thenReturn(thread);
osgiContext.registerService(CredentialsService.class, credentialsService);
osgiContext.registerInjectActivateService(membersFinder);
osgiContext.registerService(RepositoryService.class, repositoryService);
osgiContext.registerService(VoteThreadFinder.class, voteThreadFinder);
osgiContext.registerService(Mailer.class, mailer);
}
}