user = $this->createMock(IUser::class); $this->providerLoader = $this->createMock(ProviderLoader::class); $this->providerRegistry = $this->createMock(IRegistry::class); $this->mandatoryTwoFactor = $this->createMock(MandatoryTwoFactor::class); $this->session = $this->createMock(ISession::class); $this->config = $this->createMock(IConfig::class); $this->activityManager = $this->createMock(IManager::class); $this->logger = $this->createMock(LoggerInterface::class); $this->tokenProvider = $this->createMock(TokenProvider::class); $this->timeFactory = $this->createMock(ITimeFactory::class); $this->dispatcher = $this->createMock(IEventDispatcher::class); $this->manager = new Manager( $this->providerLoader, $this->providerRegistry, $this->mandatoryTwoFactor, $this->session, $this->config, $this->activityManager, $this->logger, $this->tokenProvider, $this->timeFactory, $this->dispatcher, ); $this->fakeProvider = $this->createMock(IProvider::class); $this->fakeProvider->method('getId')->willReturn('email'); $this->backupProvider = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock(); $this->backupProvider->method('getId')->willReturn('backup_codes'); $this->backupProvider->method('isTwoFactorAuthEnabledForUser')->willReturn(true); } private function prepareNoProviders() { $this->providerLoader->method('getProviders') ->with($this->user) ->willReturn([]); } private function prepareProviders() { $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->with($this->user) ->willReturn([ $this->fakeProvider->getId() => true, ]); $this->providerLoader->expects($this->once()) ->method('getProviders') ->with($this->user) ->willReturn([$this->fakeProvider]); } private function prepareProvidersWitBackupProvider() { $this->providerLoader->method('getProviders') ->with($this->user) ->willReturn([ $this->fakeProvider, $this->backupProvider, ]); } public function testIsTwoFactorAuthenticatedEnforced(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('isEnforcedFor') ->with($this->user) ->willReturn(true); $enabled = $this->manager->isTwoFactorAuthenticated($this->user); $this->assertTrue($enabled); } public function testIsTwoFactorAuthenticatedNoProviders(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('isEnforcedFor') ->with($this->user) ->willReturn(false); $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->willReturn([]); // No providers registered $this->providerLoader->expects($this->once()) ->method('getProviders') ->willReturn([]); // No providers loadable $this->assertFalse($this->manager->isTwoFactorAuthenticated($this->user)); } public function testIsTwoFactorAuthenticatedOnlyBackupCodes(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('isEnforcedFor') ->with($this->user) ->willReturn(false); $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->willReturn([ 'backup_codes' => true, ]); $backupCodesProvider = $this->createMock(IProvider::class); $backupCodesProvider ->method('getId') ->willReturn('backup_codes'); $this->providerLoader->expects($this->once()) ->method('getProviders') ->willReturn([ $backupCodesProvider, ]); $this->assertFalse($this->manager->isTwoFactorAuthenticated($this->user)); } public function testIsTwoFactorAuthenticatedFailingProviders(): void { $this->mandatoryTwoFactor->expects($this->once()) ->method('isEnforcedFor') ->with($this->user) ->willReturn(false); $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->willReturn([ 'twofactor_totp' => true, 'twofactor_u2f' => false, ]); // Two providers registered, but … $this->providerLoader->expects($this->once()) ->method('getProviders') ->willReturn([]); // … none of them is able to load, however … // … 2FA is still enforced $this->assertTrue($this->manager->isTwoFactorAuthenticated($this->user)); } public function providerStatesFixData(): array { return [ [false, false], [true, true], ]; } /** * If the 2FA registry has not been populated when a user logs in, * the 2FA manager has to first fix the state before it checks for * enabled providers. * * If any of these providers is active, 2FA is enabled * * @dataProvider providerStatesFixData */ public function testIsTwoFactorAuthenticatedFixesProviderStates(bool $providerEnabled, bool $expected): void { $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->willReturn([]); // Nothing registered yet $this->providerLoader->expects($this->once()) ->method('getProviders') ->willReturn([ $this->fakeProvider ]); $this->fakeProvider->expects($this->once()) ->method('isTwoFactorAuthEnabledForUser') ->with($this->user) ->willReturn($providerEnabled); if ($providerEnabled) { $this->providerRegistry->expects($this->once()) ->method('enableProviderFor') ->with( $this->fakeProvider, $this->user ); } else { $this->providerRegistry->expects($this->once()) ->method('disableProviderFor') ->with( $this->fakeProvider, $this->user ); } $this->assertEquals($expected, $this->manager->isTwoFactorAuthenticated($this->user)); } public function testGetProvider(): void { $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->with($this->user) ->willReturn([ $this->fakeProvider->getId() => true, ]); $this->providerLoader->expects($this->once()) ->method('getProviders') ->with($this->user) ->willReturn([$this->fakeProvider]); $provider = $this->manager->getProvider($this->user, $this->fakeProvider->getId()); $this->assertSame($this->fakeProvider, $provider); } public function testGetInvalidProvider(): void { $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->with($this->user) ->willReturn([]); $this->providerLoader->expects($this->once()) ->method('getProviders') ->with($this->user) ->willReturn([]); $provider = $this->manager->getProvider($this->user, 'nonexistent'); $this->assertNull($provider); } public function testGetLoginSetupProviders(): void { $provider1 = $this->createMock(IProvider::class); $provider2 = $this->createMock(IActivatableAtLogin::class); $this->providerLoader->expects($this->once()) ->method('getProviders') ->with($this->user) ->willReturn([ $provider1, $provider2, ]); $providers = $this->manager->getLoginSetupProviders($this->user); $this->assertCount(1, $providers); $this->assertSame($provider2, reset($providers)); } public function testGetProviders(): void { $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->with($this->user) ->willReturn([ $this->fakeProvider->getId() => true, ]); $this->providerLoader->expects($this->once()) ->method('getProviders') ->with($this->user) ->willReturn([$this->fakeProvider]); $expectedProviders = [ 'email' => $this->fakeProvider, ]; $providerSet = $this->manager->getProviderSet($this->user); $providers = $providerSet->getProviders(); $this->assertEquals($expectedProviders, $providers); $this->assertFalse($providerSet->isProviderMissing()); } public function testGetProvidersOneMissing(): void { $this->providerRegistry->expects($this->once()) ->method('getProviderStates') ->with($this->user) ->willReturn([ $this->fakeProvider->getId() => true, ]); $this->providerLoader->expects($this->once()) ->method('getProviders') ->with($this->user) ->willReturn([]); $expectedProviders = [ 'email' => $this->fakeProvider, ]; $providerSet = $this->manager->getProviderSet($this->user); $this->assertTrue($providerSet->isProviderMissing()); } public function testVerifyChallenge(): void { $this->prepareProviders(); $challenge = 'passme'; $event = $this->createMock(IEvent::class); $this->fakeProvider->expects($this->once()) ->method('verifyChallenge') ->with($this->user, $challenge) ->willReturn(true); $this->session->expects($this->once()) ->method('get') ->with('two_factor_remember_login') ->willReturn(false); $this->session->expects($this->exactly(2)) ->method('remove') ->withConsecutive( ['two_factor_auth_uid'], ['two_factor_remember_login'] ); $this->session->expects($this->once()) ->method('set') ->with(Manager::SESSION_UID_DONE, 'jos'); $this->session->method('getId') ->willReturn('mysessionid'); $this->activityManager->expects($this->once()) ->method('generateEvent') ->willReturn($event); $this->user->expects($this->any()) ->method('getUID') ->willReturn('jos'); $event->expects($this->once()) ->method('setApp') ->with($this->equalTo('core')) ->willReturnSelf(); $event->expects($this->once()) ->method('setType') ->with($this->equalTo('security')) ->willReturnSelf(); $event->expects($this->once()) ->method('setAuthor') ->with($this->equalTo('jos')) ->willReturnSelf(); $event->expects($this->once()) ->method('setAffectedUser') ->with($this->equalTo('jos')) ->willReturnSelf(); $this->fakeProvider ->method('getDisplayName') ->willReturn('Fake 2FA'); $event->expects($this->once()) ->method('setSubject') ->with($this->equalTo('twofactor_success'), $this->equalTo([ 'provider' => 'Fake 2FA', ])) ->willReturnSelf(); $token = $this->createMock(OC\Authentication\Token\IToken::class); $this->tokenProvider->method('getToken') ->with('mysessionid') ->willReturn($token); $token->method('getId') ->willReturn(42); $this->config->expects($this->once()) ->method('deleteUserValue') ->with('jos', 'login_token_2fa', '42'); $result = $this->manager->verifyChallenge('email', $this->user, $challenge); $this->assertTrue($result); } public function testVerifyChallengeInvalidProviderId(): void { $this->prepareProviders(); $challenge = 'passme'; $this->fakeProvider->expects($this->never()) ->method('verifyChallenge') ->with($this->user, $challenge); $this->session->expects($this->never()) ->method('remove'); $this->assertFalse($this->manager->verifyChallenge('dontexist', $this->user, $challenge)); } public function testVerifyInvalidChallenge(): void { $this->prepareProviders(); $challenge = 'dontpassme'; $event = $this->createMock(IEvent::class); $this->fakeProvider->expects($this->once()) ->method('verifyChallenge') ->with($this->user, $challenge) ->willReturn(false); $this->session->expects($this->never()) ->method('remove'); $this->activityManager->expects($this->once()) ->method('generateEvent') ->willReturn($event); $this->user->expects($this->any()) ->method('getUID') ->willReturn('jos'); $event->expects($this->once()) ->method('setApp') ->with($this->equalTo('core')) ->willReturnSelf(); $event->expects($this->once()) ->method('setType') ->with($this->equalTo('security')) ->willReturnSelf(); $event->expects($this->once()) ->method('setAuthor') ->with($this->equalTo('jos')) ->willReturnSelf(); $event->expects($this->once()) ->method('setAffectedUser') ->with($this->equalTo('jos')) ->willReturnSelf(); $this->fakeProvider ->method('getDisplayName') ->willReturn('Fake 2FA'); $event->expects($this->once()) ->method('setSubject') ->with($this->equalTo('twofactor_failed'), $this->equalTo([ 'provider' => 'Fake 2FA', ])) ->willReturnSelf(); $this->assertFalse($this->manager->verifyChallenge('email', $this->user, $challenge)); } public function testNeedsSecondFactor(): void { $user = $this->createMock(IUser::class); $this->session->expects($this->exactly(3)) ->method('exists') ->withConsecutive( ['app_password'], ['two_factor_auth_uid'], [Manager::SESSION_UID_DONE], ) ->willReturn(false); $this->session->method('getId') ->willReturn('mysessionid'); $token = $this->createMock(OC\Authentication\Token\IToken::class); $this->tokenProvider->method('getToken') ->with('mysessionid') ->willReturn($token); $token->method('getId') ->willReturn(42); $user->method('getUID') ->willReturn('user'); $this->config->method('getUserKeys') ->with('user', 'login_token_2fa') ->willReturn([ '42' ]); $manager = $this->getMockBuilder(Manager::class) ->setConstructorArgs([ $this->providerLoader, $this->providerRegistry, $this->mandatoryTwoFactor, $this->session, $this->config, $this->activityManager, $this->logger, $this->tokenProvider, $this->timeFactory, $this->dispatcher, ]) ->setMethods(['loadTwoFactorApp', 'isTwoFactorAuthenticated'])// Do not actually load the apps ->getMock(); $manager->method('isTwoFactorAuthenticated') ->with($user) ->willReturn(true); $this->assertTrue($manager->needsSecondFactor($user)); } public function testNeedsSecondFactorUserIsNull(): void { $user = null; $this->session->expects($this->never()) ->method('exists'); $this->assertFalse($this->manager->needsSecondFactor($user)); } public function testNeedsSecondFactorWithNoProviderAvailableAnymore(): void { $this->prepareNoProviders(); $user = null; $this->session->expects($this->never()) ->method('exists') ->with('two_factor_auth_uid') ->willReturn(true); $this->session->expects($this->never()) ->method('remove') ->with('two_factor_auth_uid'); $this->assertFalse($this->manager->needsSecondFactor($user)); } public function testPrepareTwoFactorLogin(): void { $this->user->method('getUID') ->willReturn('ferdinand'); $this->session->expects($this->exactly(2)) ->method('set') ->withConsecutive( ['two_factor_auth_uid', 'ferdinand'], ['two_factor_remember_login', true] ); $this->session->method('getId') ->willReturn('mysessionid'); $token = $this->createMock(OC\Authentication\Token\IToken::class); $this->tokenProvider->method('getToken') ->with('mysessionid') ->willReturn($token); $token->method('getId') ->willReturn(42); $this->timeFactory->method('getTime') ->willReturn(1337); $this->config->method('setUserValue') ->with('ferdinand', 'login_token_2fa', '42', '1337'); $this->manager->prepareTwoFactorLogin($this->user, true); } public function testPrepareTwoFactorLoginDontRemember(): void { $this->user->method('getUID') ->willReturn('ferdinand'); $this->session->expects($this->exactly(2)) ->method('set') ->withConsecutive( ['two_factor_auth_uid', 'ferdinand'], ['two_factor_remember_login', false] ); $this->session->method('getId') ->willReturn('mysessionid'); $token = $this->createMock(OC\Authentication\Token\IToken::class); $this->tokenProvider->method('getToken') ->with('mysessionid') ->willReturn($token); $token->method('getId') ->willReturn(42); $this->timeFactory->method('getTime') ->willReturn(1337); $this->config->method('setUserValue') ->with('ferdinand', 'login_token_2fa', '42', '1337'); $this->manager->prepareTwoFactorLogin($this->user, false); } public function testNeedsSecondFactorSessionAuth(): void { $user = $this->createMock(IUser::class); $user->method('getUID') ->willReturn('user'); $this->session->method('exists') ->willReturnCallback(function ($var) { if ($var === Manager::SESSION_UID_KEY) { return false; } elseif ($var === 'app_password') { return false; } elseif ($var === 'app_api') { return false; } return true; }); $this->session->method('get') ->willReturnCallback(function ($var) { if ($var === Manager::SESSION_UID_KEY) { return 'user'; } elseif ($var === 'app_api') { return true; } return null; }); $this->session->expects($this->once()) ->method('get') ->willReturnMap([ [Manager::SESSION_UID_DONE, 'user'], ['app_api', true] ]); $this->assertFalse($this->manager->needsSecondFactor($user)); } public function testNeedsSecondFactorSessionAuthFailDBPass(): void { $user = $this->createMock(IUser::class); $user->method('getUID') ->willReturn('user'); $this->session->method('exists') ->willReturn(false); $this->session->method('getId') ->willReturn('mysessionid'); $token = $this->createMock(OC\Authentication\Token\IToken::class); $token->method('getId') ->willReturn(40); $this->tokenProvider->method('getToken') ->with('mysessionid') ->willReturn($token); $this->config->method('getUserKeys') ->with('user', 'login_token_2fa') ->willReturn([ '42', '43', '44' ]); $this->session->expects($this->once()) ->method('set') ->with(Manager::SESSION_UID_DONE, 'user'); $this->assertFalse($this->manager->needsSecondFactor($user)); } public function testNeedsSecondFactorInvalidToken(): void { $this->prepareNoProviders(); $user = $this->createMock(IUser::class); $user->method('getUID') ->willReturn('user'); $this->session->method('exists') ->willReturn(false); $this->session->method('getId') ->willReturn('mysessionid'); $this->tokenProvider->method('getToken') ->with('mysessionid') ->willThrowException(new OC\Authentication\Exceptions\InvalidTokenException()); $this->config->method('getUserKeys')->willReturn([]); $this->assertFalse($this->manager->needsSecondFactor($user)); } public function testNeedsSecondFactorAppPassword(): void { $user = $this->createMock(IUser::class); $this->session->method('exists') ->willReturnMap([ ['app_password', true], ['app_api', true] ]); $this->assertFalse($this->manager->needsSecondFactor($user)); } public function testClearTwoFactorPending() { $this->config->method('getUserKeys') ->with('theUserId', 'login_token_2fa') ->willReturn([ '42', '43', '44' ]); $this->config->expects($this->exactly(3)) ->method('deleteUserValue') ->withConsecutive( ['theUserId', 'login_token_2fa', '42'], ['theUserId', 'login_token_2fa', '43'], ['theUserId', 'login_token_2fa', '44'], ); $this->tokenProvider->expects($this->exactly(3)) ->method('invalidateTokenById') ->withConsecutive( ['theUserId', 42], ['theUserId', 43], ['theUserId', 44], ); $this->manager->clearTwoFactorPending('theUserId'); } public function testClearTwoFactorPendingTokenDoesNotExist() { $this->config->method('getUserKeys') ->with('theUserId', 'login_token_2fa') ->willReturn([ '42', '43', '44' ]); $this->config->expects($this->exactly(3)) ->method('deleteUserValue') ->withConsecutive( ['theUserId', 'login_token_2fa', '42'], ['theUserId', 'login_token_2fa', '43'], ['theUserId', 'login_token_2fa', '44'], ); $this->tokenProvider->expects($this->exactly(3)) ->method('invalidateTokenById') ->withConsecutive( ['theUserId', 42], ['theUserId', 43], ['theUserId', 44], ) ->willReturnCallback(function ($user, $tokenId) { if ($tokenId === 43) { throw new DoesNotExistException('token does not exist'); } }); $this->manager->clearTwoFactorPending('theUserId'); } } light .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
* SonarScanner CLI
* Copyright (C) 2011-2022 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonarsource.scanner.cli;
import java.util.Map;
import java.util.Properties;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.sonar.api.utils.MessageException;
import org.sonarsource.scanner.api.EmbeddedScanner;
import org.sonarsource.scanner.api.ScanProperties;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class MainTest {
@Mock
private Exit exit;
@Mock
private Cli cli;
@Mock
private Conf conf;
@Mock
private Properties properties;
@Mock
private ScannerFactory scannerFactory;
@Mock
private EmbeddedScanner scanner;
@Mock
private Logs logs;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(scanner);
when(conf.properties()).thenReturn(properties);
}
@Test
public void should_execute_runner() {
when(cli.getInvokedFrom()).thenReturn("");
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
verify(exit).exit(Exit.SUCCESS);
verify(scannerFactory).create(properties, "");
verify(scanner, times(1)).start();
verify(scanner, times(1)).execute((Map) properties);
}
@Test
public void should_exit_with_error_on_error_during_analysis() {
EmbeddedScanner runner = mock(EmbeddedScanner.class);
Exception e = new NullPointerException("NPE");
e = new IllegalStateException("Error", e);
doThrow(e).when(runner).execute(any());
when(cli.getInvokedFrom()).thenReturn("");
when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(runner);
when(cli.isDebugEnabled()).thenReturn(true);
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
verify(exit).exit(Exit.INTERNAL_ERROR);
verify(logs).error("Error during SonarScanner execution", e);
}
@Test
public void should_exit_with_error_on_error_during_start() {
EmbeddedScanner runner = mock(EmbeddedScanner.class);
Exception e = new NullPointerException("NPE");
e = new IllegalStateException("Error", e);
doThrow(e).when(runner).start();
when(cli.getInvokedFrom()).thenReturn("");
when(cli.isDebugEnabled()).thenReturn(true);
when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(runner);
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
verify(runner).start();
verify(runner, never()).execute(any());
verify(exit).exit(Exit.INTERNAL_ERROR);
verify(logs).error("Error during SonarScanner execution", e);
}
@Test
public void show_stacktrace() {
Exception e = createException(false);
testException(e, false, false, Exit.INTERNAL_ERROR);
verify(logs).error("Error during SonarScanner execution", e);
verify(logs).error("Re-run SonarScanner using the -X switch to enable full debug logging.");
}
@Test
public void dont_show_MessageException_stacktrace() {
Exception e = createException(true);
testException(e, false, false, Exit.USER_ERROR);
verify(logs, times(5)).error(anyString());
verify(logs).error("Error during SonarScanner execution");
verify(logs).error("my message");
verify(logs).error("Caused by: A functional cause");
verify(logs).error("");
verify(logs).error("Re-run SonarScanner using the -X switch to enable full debug logging.");
}
@Test
public void dont_show_MessageException_stacktrace_embedded() {
Exception e = createException(true);
testException(e, false, true, Exit.USER_ERROR);
verify(logs, times(4)).error(anyString());
verify(logs).error("Error during SonarScanner execution");
verify(logs).error("my message");
verify(logs).error("Caused by: A functional cause");
verify(logs).error("");
}
@Test
public void show_MessageException_stacktrace_in_debug() {
Exception e = createException(true);
testException(e, true, false, Exit.USER_ERROR);
verify(logs, times(1)).error(anyString(), any(Throwable.class));
verify(logs).error("Error during SonarScanner execution", e);
}
@Test
public void show_MessageException_stacktrace_in_debug_embedded() {
Exception e = createException(true);
testException(e, true, true, Exit.USER_ERROR);
verify(logs, times(1)).error(anyString(), any(Throwable.class));
verify(logs).error("Error during SonarScanner execution", e);
}
@Test
public void show_stacktrace_in_debug() {
Exception e = createException(false);
testException(e, true, false, Exit.INTERNAL_ERROR);
verify(logs).error("Error during SonarScanner execution", e);
verify(logs, never()).error("Re-run SonarScanner using the -X switch to enable full debug logging.");
}
private void testException(Exception e, boolean debugEnabled, boolean isEmbedded, int expectedExitCode) {
when(cli.isDebugEnabled()).thenReturn(debugEnabled);
when(cli.isEmbedded()).thenReturn(isEmbedded);
when(cli.getInvokedFrom()).thenReturn("");
EmbeddedScanner runner = mock(EmbeddedScanner.class);
doThrow(e).when(runner).execute(any());
when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(runner);
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
verify(exit).exit(expectedExitCode);
}
private Exception createException(boolean messageException) {
Exception e;
if (messageException) {
e = new MessageException("my message", new IllegalStateException("A functional cause"));
} else {
e = new IllegalStateException("Error", new NullPointerException("NPE"));
}
return e;
}
@Test
public void should_only_display_version() {
Properties p = new Properties();
when(cli.isDisplayVersionOnly()).thenReturn(true);
when(cli.getInvokedFrom()).thenReturn("");
when(conf.properties()).thenReturn(p);
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
InOrder inOrder = Mockito.inOrder(exit, scannerFactory);
inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
inOrder.verify(scannerFactory, times(1)).create(p, "");
inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
}
@Test
public void should_skip() {
Properties p = new Properties();
p.setProperty(ScanProperties.SKIP, "true");
when(conf.properties()).thenReturn(p);
when(cli.getInvokedFrom()).thenReturn("");
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
verify(logs).info("SonarScanner analysis skipped");
InOrder inOrder = Mockito.inOrder(exit, scannerFactory);
inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
inOrder.verify(scannerFactory, times(1)).create(p, "");
inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
}
@Test
public void shouldLogServerVersion() {
when(scanner.serverVersion()).thenReturn("5.5");
Properties p = new Properties();
when(cli.isDisplayVersionOnly()).thenReturn(true);
when(cli.getInvokedFrom()).thenReturn("");
when(conf.properties()).thenReturn(p);
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
verify(logs).info("Analyzing on SonarQube server 5.5");
}
@Test
public void should_log_SonarCloud_server() {
Properties p = new Properties();
p.setProperty("sonar.host.url", "https://sonarcloud.io");
when(conf.properties()).thenReturn(p);
when(cli.getInvokedFrom()).thenReturn("");
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
verify(logs).info("Analyzing on SonarCloud");
}
// SQSCANNER-57
@Test
public void should_return_true_is_sonar_cloud() {
Properties properties = new Properties();
properties.setProperty("sonar.host.url", "https://sonarcloud.io");
assertThat(Main.isSonarCloud(properties)).isTrue();
}
// SQSCANNER-57
@Test
public void should_return_false_is_sonar_cloud() {
Properties properties = new Properties();
properties.setProperty("sonar.host.url", "https://mysonarqube.com:9000/");
assertThat(Main.isSonarCloud(properties)).isFalse();
}
// SQSCANNER-57
@Test
public void should_return_false_is_sonar_cloud_host_is_null() {
assertThat(Main.isSonarCloud(new Properties())).isFalse();
}
@Test
public void should_configure_logging() {
Properties analysisProps = testLogging("sonar.verbose", "true");
assertThat(analysisProps.getProperty("sonar.verbose")).isEqualTo("true");
}
@Test
public void should_configure_logging_trace() {
Properties analysisProps = testLogging("sonar.log.level", "TRACE");
assertThat(analysisProps.getProperty("sonar.log.level")).isEqualTo("TRACE");
}
@Test
public void should_configure_logging_debug() {
Properties analysisProps = testLogging("sonar.log.level", "DEBUG");
assertThat(analysisProps.getProperty("sonar.log.level")).isEqualTo("DEBUG");
}
private Properties testLogging(String propKey, String propValue) {
Properties p = new Properties();
p.put(propKey, propValue);
when(conf.properties()).thenReturn(p);
when(cli.getInvokedFrom()).thenReturn("");
Main main = new Main(exit, cli, conf, scannerFactory, logs);
main.execute();
// Logger used for callback should have debug enabled
verify(logs).setDebugEnabled(true);
ArgumentCaptor<Properties> propertiesCapture = ArgumentCaptor.forClass(Properties.class);
verify(scanner).execute((Map) propertiesCapture.capture());
return propertiesCapture.getValue();
}
}