/* * Copyright 2015 Evgeny Dolganov (evgenij.dolganov@gmail.com). * * 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 och.front.service; import static java.math.BigDecimal.*; import static java.util.Collections.*; import static och.api.model.PropKey.*; import static och.api.model.RemoteCache.*; import static och.api.model.billing.PaymentBase.*; import static och.api.model.billing.PaymentProvider.*; import static och.api.model.billing.PaymentStatus.*; import static och.api.model.billing.PaymentType.*; import static och.api.model.chat.account.ChatAccountPrivileges.*; import static och.api.model.chat.account.PrivilegeType.*; import static och.api.model.tariff.Tariff.*; import static och.api.model.tariff.TariffMath.*; import static och.api.model.user.SecurityContext.*; import static och.api.model.user.UserRole.*; import static och.api.model.user.UserStatus.*; import static och.comp.db.main.table.MainTables.*; import static och.comp.ops.BillingOps.*; import static och.comp.paypal.PaypalClientStub.*; import static och.front.service.SecurityService.*; import static och.util.DateUtil.*; import static och.util.StringUtil.*; import static och.util.Util.*; import static och.util.sql.Dialect.*; import static och.util.sql.SingleTx.*; import java.io.File; import java.math.BigDecimal; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import javax.servlet.http.Cookie; import och.api.exception.InvalidInputException; import och.api.exception.ValidationException; import och.api.exception.billing.NoDataToConfirmPaymentException; import och.api.exception.chat.AccountsLimitException; import och.api.exception.chat.ChatAccountBlockedException; import och.api.exception.chat.ChatAccountNotPausedException; import och.api.exception.chat.ChatAccountPausedException; import och.api.exception.chat.HostBlockedException; import och.api.exception.chat.NoAvailableServerException; import och.api.exception.chat.NoChatAccountException; import och.api.exception.tariff.ChangeTariffLimitException; import och.api.exception.tariff.NotPublicTariffException; import och.api.exception.tariff.OperatorsLimitException; import och.api.exception.tariff.TariffNotFoundException; import och.api.exception.tariff.UpdateTariffOperatorsLimitException; import och.api.exception.user.AccessDeniedException; import och.api.exception.user.BannedUserException; import och.api.exception.user.DuplicateUserDataException; import och.api.exception.user.InvalidLoginDataForUpdateException; import och.api.exception.user.InvalidUserActivationCodeException; import och.api.exception.user.NotActivatedUserException; import och.api.exception.user.UnmodifiableAdminUserException; import och.api.exception.user.UserActivationExpiredException; import och.api.exception.user.UserNotFoundException; import och.api.exception.user.UserSessionAlreadyExistsException; import och.api.model.PropKey; import och.api.model.billing.AdminSyncResp; import och.api.model.billing.PayData; import och.api.model.billing.PaymentBase; import och.api.model.billing.PaymentExt; import och.api.model.billing.PaymentProvider; import och.api.model.billing.PaymentStatus; import och.api.model.billing.PaymentType; import och.api.model.chat.account.ChatAccount; import och.api.model.chat.account.PrivilegeType; import och.api.model.chat.config.Key; import och.api.model.chat.host.ClientHost; import och.api.model.remtoken.ClientRemToken; import och.api.model.remtoken.RemToken; import och.api.model.server.ServerRow; import och.api.model.tariff.Tariff; import och.api.model.user.LoginUserReq; import och.api.model.user.UpdateUserReq; import och.api.model.user.User; import och.api.model.user.UserExt; import och.api.model.user.UserRole; import och.comp.billing.standalone.BillingSyncService; import och.comp.billing.standalone.HostMultiOwnersAlarmService; import och.comp.cache.Cache; import och.comp.cache.client.CacheClient; import och.comp.cache.impl.CacheImpl; import och.comp.cache.server.CacheServerContext; import och.comp.cache.server.CacheSever; import och.comp.db.base.universal.UniversalQueries; import och.comp.db.main.MainDb; import och.comp.db.main.table.MainTables; import och.comp.db.main.table._f.IsFull; import och.comp.db.main.table._f.TariffLastPay; import och.comp.db.main.table._f.TariffStart; import och.comp.db.main.table.billing.CreatePayment; import och.comp.db.main.table.billing.GetPaymentByExternalId; import och.comp.db.main.table.billing.GetPaymentById; import och.comp.db.main.table.billing.GetStartBonusByUserId; import och.comp.db.main.table.billing.SelectUserBalanceById; import och.comp.db.main.table.billing.UpdateUserAccsBlocked; import och.comp.db.main.table.billing.UpdateUserBalance; import och.comp.db.main.table.billing.UpdateUserBalanceUnsafe; import och.comp.db.main.table.chat.GetAllChatAccounts; import och.comp.db.main.table.chat.GetChatAccount; import och.comp.db.main.table.chat.UpdateAllChatAccounts; import och.comp.db.main.table.chat.UpdateChatAccountByUid; import och.comp.db.main.table.chat.host.CreateClientHost; import och.comp.db.main.table.chat.host.CreateClientHostAccOwner; import och.comp.db.main.table.chat.host.DeleteClientHostAccOwner; import och.comp.db.main.table.chat.host.UpdateClientHostImportant; import och.comp.db.main.table.chat.privilege.GetChatAccountPrivileges; import och.comp.db.main.table.remtoken.SelectRemTokensByUser; import och.comp.db.main.table.server.GetAllServers; import och.comp.db.main.table.server.UpdateServerById; import och.comp.db.main.table.tariff.GetAllTariffs; import och.comp.db.main.table.user.SelectUserById; import och.comp.mail.stub.MailServiceStub; import och.comp.mail.stub.SenderStub; import och.comp.ops.BillingOps; import och.comp.paypal.PaypalClientStub; import och.comp.paypal.standalone.PaypalPaymentsSynchService; import och.email.parser.ActivationEmailParser; import och.email.parser.RestorePswEmailParser; import och.front.service.ChatService.UpdateTariffOps; import och.front.service.model.UserAccInfo; import och.service.props.WriteProps; import och.service.props.impl.MapProps; import och.util.DateUtil; import och.util.StringUtil; import och.util.concurrent.ExecutorsUtil; import och.util.model.Pair; import och.util.servlet.WebUtil; import och.util.sql.ConcurrentUpdateSqlException; import org.apache.commons.logging.Log; import org.h2.tools.Server; import org.junit.Before; import org.junit.Test; import test.BaseTest; import test.TestException; import web.MockHttpServletRequest; import web.MockHttpServletResponse; import web.MockServletContext; public class FrontAppTest extends BaseTest { public static final String TEMPLATES_PATH = "./server-front/web/WEB-INF/templates"; private static Log log = getLog(FrontAppTest.class); SenderStub mailSender = new SenderStub(); int cachePort = 12159; MockServletContext servletContext = new MockServletContext(); MockHttpServletRequest req = new MockHttpServletRequest(); MockHttpServletResponse resp = new MockHttpServletResponse(); ArrayList<Future<?>> asyncFutures = new ArrayList<>(); ArrayList<Future<?>> scheduleFutures = new ArrayList<>(); PaypalClientStub paypalClient = new PaypalClientStub(); MapProps props; FrontApp app; FrontAppContext c; MainDb db; UniversalQueries universal; ChatService chats; SecurityService security; CacheSever cacheSever; UserService users; BillingService billing; CacheClient cacheClient; long userId1; String login1 = "user"; String mail1 = "user@user.ru"; String psw1 = "123"; long userId2; String login2 = "user2"; String mail2 = "user2@user.ru"; String psw2 = StringUtil.createStr('я', 200); long userId3; String login3 = "user3"; String mail3 = "user3@user.ru"; String psw3 = "123"; long userId4; String login4 = "user4"; String mail4 = "user4@user.ru"; String psw4 = "123"; String cacheSecureKey = "some132"; String server1HttpUrl = "http://test1"; String server1HttpsUrl = "https://test1"; String server2HttpUrl = "http://test2"; String server2HttpsUrl = "https://test2"; String server3HttpUrl = "http://test3"; String server3HttpsUrl = "https://test3"; long serverId1 = 1; long serverId2 = 2; long serverId3; @Before public void before() throws Exception{ props = baseFrontProps(TEST_DIR); props.putVal(cache_remote_port, cachePort); props.putVal(db_reinit, true); props.putVal(chats_server_init_urls, server1HttpUrl+" "+server1HttpsUrl+","+server2HttpUrl+" "+server2HttpsUrl); props.putVal(app_debug_createRemoteData, false); props.putVal(billing_sync_debug_DisableTimer, true); props.putVal(mail_storeToDisc, false); props.putVal(billing_sync_fillBlockedCacheOnStartDelay, 0); props.putVal(billing_sync_lastSyncStore, false); props.putVal(db_debug_LogSql, true); props.putVal(cache_encyptedKey, cacheSecureKey); cacheSever = new CacheSever(cachePort, 2, 10000, cacheSecureKey, props); cacheSever.runAsync(); app = FrontApp.create( props, servletContext, new MailServiceStub(mailSender, props), paypalClient); c = app.c; db = c.db; universal = db.universal; chats = app.chats; users = app.users; security = app.security; cacheClient = c.cache; billing = app.billing; c.async.addListener((future) -> asyncFutures.add(future)); c.async.addScheduleListener((future) -> scheduleFutures.add(future)); cacheClient.addListener((future) -> asyncFutures.add(future)); } public static MapProps baseFrontProps(File testDir) throws Exception{ MapProps props = new MapProps(); putDbProps(props, testDir); props.putVal(admin_Emails, "admin@host.com"); props.putVal(users_activationUrl, "http://test"); props.putVal(cache_remote_maxConns, 2); props.putVal(cache_remote_idleConns, 2); props.putVal(templates_path, TEMPLATES_PATH); props.putVal(captcha_publicKey, "test"); props.putVal(captcha_privateKey, "test"); props.putVal("", ""); return props; } public static void putDbProps(WriteProps props, File testDir) throws Exception{ boolean usePostgre = false; if(usePostgre){ props.putVal(db_dialect, DB_POSTGRESQL); props.putVal(db_driver, "org.postgresql.Driver"); props.putVal(db_url, "jdbc:postgresql://localhost/och-test"); props.putVal(db_user, ""); props.putVal(db_psw, ""); props.putVal(db_maxConnections, 10); props.putVal(db_idleConnections, 5); } //h2 else { int serverPort = 9400; runH2ServerIfNeed(testDir, serverPort); Class.forName("org.h2.Driver"); int logMode = 1; //1-err,2-info,3-debug //String url = "jdbc:h2:mem:db-"+randomSimpleId() + ";DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT="+logMode; //String url = "jdbc:h2:"+new File(testDir, "test.db").getAbsolutePath(); String url = "jdbc:h2:tcp://localhost:"+serverPort+"/~/test"; props.putVal(db_dialect, DB_H2); props.putVal(db_driver, "org.h2.Driver"); props.putVal(db_url, url); props.putVal(db_user, "sa"); props.putVal(db_psw, ""); props.putVal(db_maxConnections, 10); props.putVal(db_idleConnections, 5); } } private static void runH2ServerIfNeed(File testDir, int port) { try { Server.createTcpServer( "-tcpPort", ""+port, "-tcpAllowOthers").start(); }catch(Exception e){ log.error("can't runH2Server: "+e); } } @Test public void test_all() throws Exception { //DB test_init_db(); test_db_getServers(); //USER test_user_create(); test_user_get(); test_user_duplicates(); test_user_invalid_inputs(); test_user_unexists(); test_user_activate(); test_user_ban(); test_user_unban(); test_user_activate_from_email_text(); test_user_invalid_activation_states(); test_user_send_activation_email_again(); test_user_change_psw(); test_user_update(); test_user_psw_secure(); test_ban_user_runtime_with_exists_session(); //ROLE test_set_get_roles(); //SECURITY test_create_restore_remMe(); test_logout_remMe(); test_create_without_remMe(); test_remMeToken_secure(); test_remMeToken_maxCount(); test_invalidLoginsCount(); //chats test_chats_createServerAndAcc_BySystem(); test_chats_createAccs_byUser(); test_chats_renameAccs_BySystem_ByUser(); test_chats_changePrivsForUser(); test_chats_operatorsLimits(); test_chats_accsLimits(); test_chats_accPauseLimits(); test_chats_nicknames(); //billing test_billing_atomicChangeBalance(); test_billing_put_balances_to_cache(); test_billing_get_balance_from_cache_or_db(); test_billing_paypal_paySteps(); test_billing_paySync(); test_billing_payBill(); test_billing_monthBill(); test_billing_sendErrorsWithEmails(); test_billing_callFromCacheFlag(); test_billing_blockUserAccs(); test_billing_promoStartBonus(); test_billing_2checkout_paySteps(); //tariffs test_tariff_defaultTariffs(); test_tariff_update_invalidInputs_limitations(); test_tariff_update_maxInDayLimit(); test_tariff_update(); //tariffs, billing concurrents test_tariff_billing_concurrent(); //client hosts test_clientHosts_Crud(); test_clientHosts_AlarmDetect(); test_clientHosts_Block(); } private void test_billing_promoStartBonus() throws Exception { long userId = userId1; BigDecimal initBalance = null; pushToSecurityContext_SYSTEM_USER(); try { initBalance = billing.getUserBalance(userId); }finally { popUserFromSecurityContext(); } assertFalse(universal.selectOne(new GetStartBonusByUserId(userId)).startBonusAdded); //first call { assertTrue(billing.addStartBonus(userId)); assertTrue(universal.selectOne(new GetStartBonusByUserId(userId)).startBonusAdded); } //second call { assertFalse(billing.addStartBonus(userId)); assertTrue(universal.selectOne(new GetStartBonusByUserId(userId)).startBonusAdded); } lastFrom(asyncFutures).get(); //check balance pushToSecurityContext_SYSTEM_USER(); try { BigDecimal curBalance = billing.getUserBalance(userId); int deltaVal = promo_startBonus.bigDecimalDefVal().intValue(); assertEquals(deltaVal, curBalance.subtract(initBalance).intValue()); BigDecimal cacheVal = tryParseBigDecimal(cacheClient.tryGetVal(getBalanceCacheKey(userId)), null) ; assertEquals(deltaVal, cacheVal.subtract(initBalance).intValue()); }finally { popUserFromSecurityContext(); } } private void test_clientHosts_Block() { MockHttpServletRequest req = new MockHttpServletRequest(); req.addHeader("Referer", "http://ya.ru"); chats.checkAndLogReferer(req, null, "demo"); //by host { props.putVal(chats_blockByHost+"_ya.ru", true); try { chats.checkAndLogReferer(req, null, "demo"); fail_exception_expected(); }catch(HostBlockedException e){ //ok } props.putVal(chats_blockByHost+"_ya.ru", false); chats.checkAndLogReferer(req, null, "demo"); } //by host and uid { props.putVal(chats_blockByHost+"_ya.ru_demo", true); try { chats.checkAndLogReferer(req, null, "demo"); fail_exception_expected(); }catch(HostBlockedException e){ //ok } props.putVal(chats_blockByHost+"_ya.ru_demo", false); chats.checkAndLogReferer(req, null, "demo"); } //by host and accs owner { props.putVal(chats_blockByHost+"_ya.ru_owner_100", true); try { chats.checkAndLogReferer(req, null, "demo"); fail_exception_expected(); }catch(HostBlockedException e){ //ok } props.putVal(chats_blockByHost+"_ya.ru_owner_100", false); chats.checkAndLogReferer(req, null, "demo"); } } private void test_clientHosts_AlarmDetect() throws Exception { boolean important = true; long userId = 100; long userId2 = 101; String name1 = "1.ru"; String refer1 = "http://"+name1; String refer2 = "http://2.ru"; //create stat pushToSecurityContext_SYSTEM_USER(); try { universal.update(new DeleteClientHostAccOwner(userId)); universal.update(new DeleteClientHostAccOwner(userId2)); assertEquals(0, db.clientHosts.getHostsWithOwners(important, 1).size()); String acc1 = chats.getOwnerAccIds(userId).get(0); String acc2 = chats.getOwnerAccIds(userId2).get(0); assertFalse(chats.saveClientsHostsStat()); chats.checkAndLogReferer(req, refer1, acc1).get(); chats.checkAndLogReferer(req, refer1, acc2).get(); chats.checkAndLogReferer(req, refer2, acc1).get(); assertTrue(chats.saveClientsHostsStat()); }finally { popUserFromSecurityContext(); } props.putVal(chats_hosts_multiOwners_DisableSendErrors, false); MailServiceStub mailService = new MailServiceStub(mailSender, props); mailSender.tasks.clear(); HostMultiOwnersAlarmService alarm = new HostMultiOwnersAlarmService(); alarm.setCacheServerContext(new CacheServerContext(props, cacheSever, db, mailService)); alarm.init(); //есть мульти владельцы - есть письмо { assertEquals(2, db.clientHosts.getHostsWithOwners(important, 1).size()); assertEquals(1, db.clientHosts.getHostsWithOwners(important, 2).size()); alarm.doCheckWork(); assertEquals(1, mailSender.tasks.size()); } //поменяли флаг критичности - нет письма { universal.update(new UpdateClientHostImportant(name1, false)); mailSender.tasks.clear(); assertEquals(0, db.clientHosts.getHostsWithOwners(important, 2).size()); assertEquals(1, db.clientHosts.getHostsWithOwners(important, 1).size()); alarm.doCheckWork(); assertEquals(0, mailSender.tasks.size()); } //вернули флаг критичности - есть письмо { universal.update(new UpdateClientHostImportant(name1, true)); mailSender.tasks.clear(); assertEquals(1, db.clientHosts.getHostsWithOwners(important, 2).size()); assertEquals(2, db.clientHosts.getHostsWithOwners(important, 1).size()); alarm.doCheckWork(); assertEquals(1, mailSender.tasks.size()); } //нет мульти владельцев - нет письма { universal.update(new DeleteClientHostAccOwner(userId)); mailSender.tasks.clear(); assertEquals(0, db.clientHosts.getHostsWithOwners(important, 2).size()); assertEquals(1, db.clientHosts.getHostsWithOwners(important, 1).size()); alarm.doCheckWork(); assertEquals(0, mailSender.tasks.size()); } } private void test_clientHosts_Crud() throws Exception { long hostId1 = 0; long hostId2 = 0; String name1 = "ya.ru"; String name2 = "ya.ru2"; boolean important = true; long userId = 100; long userId2 = 101; //create host { hostId1 = universal.nextSeqFor(MainTables.client_hosts); universal.update(new CreateClientHost(new ClientHost(hostId1, name1, important))); List<ClientHost> list = db.clientHosts.getHostsWithOwners(important, 0); assertEquals(1, list.size()); assertEquals(name1, list.get(0).name); assertEquals(0, db.clientHosts.getHostsWithOwners( ! important, 0).size()); assertEquals(0, db.clientHosts.getHostsWithOwners( important, 1).size()); hostId2 = universal.nextSeqFor(MainTables.client_hosts); universal.update(new CreateClientHost(new ClientHost(hostId2, name2, important))); assertEquals(2, db.clientHosts.getHostsWithOwners( important, 0).size()); } //create link { universal.update(new CreateClientHostAccOwner(hostId1, userId)); try { universal.update(new CreateClientHostAccOwner(hostId1, userId)); fail_exception_expected(); }catch(SQLException e){ //ok } universal.update(new CreateClientHostAccOwner(hostId1, userId2)); List<ClientHost> hosts = db.clientHosts.getHostsWithOwners( important, 0); assertEquals(2, hosts.size()); ClientHost host = hosts.get(0); assertNotNull(host.owners); assertEquals(2, host.owners.size()); assertEquals(userId, host.owners.get(0).id); assertEquals(userId2, host.owners.get(1).id); assertEquals(1, db.clientHosts.getHostsWithOwners(important, 1).size()); assertEquals(1, db.clientHosts.getHostsWithOwners(important, 2).size()); } //create stat pushToSecurityContext_SYSTEM_USER(); try { universal.update(new DeleteClientHostAccOwner(userId)); universal.update(new DeleteClientHostAccOwner(userId2)); assertEquals(0, db.clientHosts.getHostsWithOwners(important, 1).size()); String acc1 = chats.getOwnerAccIds(userId).get(0); String acc2 = chats.getOwnerAccIds(userId2).get(0); assertFalse(chats.saveClientsHostsStat()); chats.checkAndLogReferer(req, "http://1.ru", acc1).get(); chats.checkAndLogReferer(req, "http://1.ru", acc2).get(); chats.checkAndLogReferer(req, "http://2.ru", acc1).get(); assertTrue(chats.saveClientsHostsStat()); assertEquals(1, db.clientHosts.getHostsWithOwners(important, 2).size()); assertEquals(2, db.clientHosts.getHostsWithOwners(important, 1).size()); }finally { popUserFromSecurityContext(); } } private void test_chats_nicknames() throws Exception { long ownerId = 100; String accUid = "demo"; String nick = "some test nick"; pushToSecurityContext_SYSTEM_USER(()->{ ChatAccount acc = chats.getAccByUid(accUid, false); assertEquals(null, db.universal.selectOne(new GetChatAccountPrivileges(acc.id, ownerId)).nickname); //set chats.setNickname(accUid, ownerId, nick); //check model Map<Long, UserAccInfo> map = chats.getAccOperators(accUid); assertTrue(map.size() > 0); UserAccInfo info = map.get(ownerId); assertNotNull(info); assertEquals(nick, info.nickname); //check db assertEquals(nick, db.universal.selectOne(new GetChatAccountPrivileges(acc.id, ownerId)).nickname); //check to long try { chats.setNickname(accUid, ownerId, randomStr(MAX_NICKNAME_SIZE+1)); fail_exception_expected(); }catch(ValidationException e){ //ok } pushToSecurityContext(new User(userId1)); try { //можно редактировать свой никнейм chats.setNickname(accUid, nick); //но чужой можно только для владельца или модера chats.setNickname(accUid, ownerId, nick); fail_exception_expected(); }catch(AccessDeniedException e){ //ok }finally { popUserFromSecurityContext(); } }); } private void test_chats_accPauseLimits() throws Exception { String userLogin = "u_PauseLimits"; String userMail = userLogin+"@dd.dd"; long userId = -1; int maxChangesInDay = props.getIntVal(tariffs_maxChangedInDay); //создаем юзера pushToSecurityContext_SYSTEM_USER(); try { userId = users.createUser(new User(userLogin, userMail), "123", false); }finally { popUserFromSecurityContext(); } pushToSecurityContext(new User(userId)); try { String uid = chats.createAccByUser("pauseLimits_1"); long initTariff = chats.getAccsForOperator(userId).get(0).tariffId; //нельзя убирать с паузы просто так try { chats.unpauseAccByUser(uid); fail_exception_expected(); }catch(ChatAccountNotPausedException e){ //ok } //нельзя проставлять паузы через метод смены тарифа try{ chats.updateAccTariffByUser(uid, PAUSE_TARIFF_ID); fail_exception_expected(); }catch(InvalidInputException e){ //ok } //паузим макс количество раз for (int i = 0; i < maxChangesInDay; i++) { chats.pauseAccByUser(uid); assertEquals(PAUSE_TARIFF_ID, chats.getAccsForOperator(userId).get(0).tariffId); chats.unpauseAccByUser(uid); assertEquals(initTariff, chats.getAccsForOperator(userId).get(0).tariffId); } //больше нельзя try { chats.pauseAccByUser(uid); fail_exception_expected(); }catch(ChangeTariffLimitException e){ //ok } assertEquals(initTariff, chats.getAccsForOperator(userId).get(0).tariffId); }finally { popUserFromSecurityContext(); } } private void test_chats_accsLimits() throws Exception { String userLogin = "u_accsLimits"; String userMail = userLogin+"@dd.dd"; long userId = -1; int defaultMaxAccs = props.getIntVal(chats_maxAccsForUser); //создаем юзера pushToSecurityContext_SYSTEM_USER(); try { userId = users.createUser(new User(userLogin, userMail), "123", false); }finally { popUserFromSecurityContext(); } pushToSecurityContext(new User(userId)); try { //создаем макс кол-во чатов { for (int i = 0; i < defaultMaxAccs; i++) { chats.createAccByUser("some"); } } //след.акк будет вызывать ошибку try { chats.createAccByUser("some"); fail_exception_expected(); }catch(AccountsLimitException e){ //ok } //увеличиваем макс для конкретного юзера props.putVal(chats_maxAccsForUser+"-"+userId, defaultMaxAccs+1); chats.createAccByUser("some"); try { chats.createAccByUser("some"); fail_exception_expected(); }catch(AccountsLimitException e){ //ok } }finally { popUserFromSecurityContext(); } } private void test_billing_blockUserAccs() throws Exception { MailServiceStub mailService = new MailServiceStub(mailSender, props); //Отключаем все другие акки от апдейта Date longFuture = parseStandartDateTime("02.09.2040 3:00:00"); universal.update(new UpdateAllChatAccounts(new TariffStart(longFuture), new TariffLastPay(longFuture))); MapProps paypalProps = new MapProps(); paypalProps.putVal(paypal_sync_debug_DisableTimer, true); PaypalPaymentsSynchService paySync = new PaypalPaymentsSynchService(); paySync.setCacheServerContext(new CacheServerContext(paypalProps, cacheSever, db, mailService)); paySync.setClient(paypalClient); paySync.init(); BillingSyncService billingSync = new BillingSyncService(); billingSync.setCacheServerContext(new CacheServerContext(props, cacheSever, db, mailService)); billingSync.init(); ArrayList<Pair<Long, Boolean>> blockReqs = new ArrayList<>(); BillingOps.SEND_ACCS_BLOCKED_LISTENER = (ownerId, val) -> blockReqs.add(new Pair<Long, Boolean>(ownerId, val)); pushToSecurityContext_SYSTEM_USER(); try { int tariffId = 2; long userId = userId4; String accUid = "billing_blockUserAccs"; List<String> oldAccs = db.chats.getOwnerAccs(userId); assertTrue(oldAccs.size() > 0); //create acc chats.createAcc(serverId1, accUid, userId, "test_monthBill", tariffId); chats.setOperatorForAcc(accUid, userId); assertEquals(1, chats.getAccOperators(accUid).size()); //ушли в минус - заблокированы { correctBalance(userId, new BigDecimal(4.99d)); assertEquals("4.99", billing.getUserBalance(userId).toString()); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-5.00"; assertFalse(findBalance(universal, userId).accsBlocked); Date pastPay = parseStandartDateTime("01.08.2014 00:00:00"); Date now = parseStandartDateTime("02.09.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, billingSync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //заблокированы assertEquals("-0.01", billing.getUserBalance(userId).toString()); assertTrue(findBalance(universal, userId).accsBlocked); //расчет тарифов обновился assertEquals(parseStandartDateTime("01.09.2014 00:00:00"), universal.selectOne(new GetChatAccount(accUid)).tariffLastPay); //старые тарифы не обновили дату оплаты, т.к. она у них позже текущей for(String uid : oldAccs) assertEquals(longFuture, universal.selectOne(new GetChatAccount(uid)).tariffLastPay); //послан запрос на блокировку assertEquals(1, blockReqs.size()); assertTrue(blockReqs.get(0).second); blockReqs.clear(); //проверка ограничений pushToSecurityContext(new User(userId)); try { //не можем менять тарифы юзером try { chats.updateAccTariffByUser(accUid, tariffId); fail_exception_expected(); } catch(ChatAccountBlockedException e){ //ok } //не можем создавать новые акки try { chats.createAccByUser("some"); fail_exception_expected(); } catch(ChatAccountBlockedException e){ //ok } //не можем паузить try { chats.pauseAccByUser(accUid); fail_exception_expected(); } catch(ChatAccountBlockedException e){ //ok } //не можем анпаузить try { chats.unpauseAccByUser(accUid); fail_exception_expected(); } catch(ChatAccountBlockedException e){ //ok } }finally { popUserFromSecurityContext(); } //в кеше есть флаги блока для каждого акка for(String uid : db.chats.getOwnerAccs(userId)){ assertEquals("accUid="+uid, true, isAccBlockedFromCache(cacheClient, uid)); } //если заново стартанем синк сервер, то кеш будет заполнен { Cache newCache = new CacheImpl(0); BillingSyncService otherBillingSync = new BillingSyncService(); otherBillingSync.setCacheServerContext(new CacheServerContext(props, newCache, db, mailService)); otherBillingSync.init(); for(String uid : db.chats.getOwnerAccs(userId)){ assertEquals(true, isAccBlockedFromCache(newCache, uid)); } } //так же доступны данные через публичное апи чатов pushToSecurityContext(new User(userId)); try { assertTrue(chats.getBlockedAccs().size() > 0); for(ChatAccount acc : chats.getAccsForOperator(userId)){ assertEquals(true, acc.blocked); } }finally { popUserFromSecurityContext(); } } //прошел месяц -- все еще заблочены -- расчетов по тарифу нет { assertTrue(findBalance(universal, userId).accsBlocked); BigDecimal initBalance = billing.getUserBalance(userId); Date now = parseStandartDateTime("01.10.2014 3:00:00"); assertEquals(1, billingSync.doSyncWork(false, now)); assertEquals("0.00", getDeltaVal(userId, initBalance)); assertEquals("-0.01", billing.getUserBalance(userId).toString()); //но расчет тарифов обновился assertTrue(findBalance(universal, userId).accsBlocked); assertEquals(parseStandartDateTime("01.10.2014 00:00:00"), universal.selectOne(new GetChatAccount(accUid)).tariffLastPay); //старые тарифы не обновили дату оплаты, т.к. она у них позже текущей for(String uid : oldAccs) assertEquals(longFuture, universal.selectOne(new GetChatAccount(uid)).tariffLastPay); //не было запроса на блокировку assertEquals(0, blockReqs.size()); //в кеше есть флаги блока для каждого акка for(String uid : db.chats.getOwnerAccs(userId)){ assertEquals(true, BillingOps.isAccBlockedFromCache(cacheClient, uid)); } } //пользователь закинул деньги спустя неделю в ноль и его разблокировали { Date now = parseStandartDateTime("12.10.2014 15:45:00"); pushToSecurityContext(new User(userId)); try { paypalClient.payAmount = new BigDecimal("0.01"); billing.sendPayReq(paypal_key.strDefVal(), paypalClient.payAmount); billing.paypal_preparePayConfirm(randomSimpleId(), STUB_TOKEN); billing.paypal_finishPayment(now); } finally { popUserFromSecurityContext(); } assertEquals("0.00", billing.getUserBalance(userId).toString()); assertFalse(findBalance(universal, userId).accsBlocked); assertEquals(now, universal.selectOne(new GetChatAccount(accUid)).tariffLastPay); //старые тарифы не обновили дату оплаты, т.к. она у них позже текущей for(String uid : oldAccs) assertEquals(longFuture, universal.selectOne(new GetChatAccount(uid)).tariffLastPay); //послан запрос на разблокировку assertEquals(1, blockReqs.size()); assertFalse(blockReqs.get(0).second); blockReqs.clear(); //можем менять тарифы юзером pushToSecurityContext(new User(userId)); try { chats.updateAccTariffByUser(accUid, tariffId); }finally { popUserFromSecurityContext(); } //в кеше нет флагов блока для каждого акка for(String uid : db.chats.getOwnerAccs(userId)){ assertEquals(false, BillingOps.isAccBlockedFromCache(cacheClient, uid)); } //если заново стартанем синк сервер, то кеш будет верным { Cache newCache = new CacheImpl(0); BillingSyncService otherBillingSync = new BillingSyncService(); otherBillingSync.setCacheServerContext(new CacheServerContext(props, newCache, db, mailService)); otherBillingSync.init(); for(String uid : db.chats.getOwnerAccs(userId)){ assertEquals(false, isAccBlockedFromCache(newCache, uid)); } } //так же доступны данные через публичное апи чатов pushToSecurityContext(new User(userId)); try { assertTrue(chats.getBlockedAccs().size() == 0); for(ChatAccount acc : chats.getAccsForOperator(userId)){ assertEquals(false, acc.blocked); } }finally { popUserFromSecurityContext(); } } //прошел месяц, снова сняли деньги и заблочили { assertFalse(findBalance(universal, userId).accsBlocked); BigDecimal initBalance = billing.getUserBalance(userId); Date now = parseStandartDateTime("01.11.2014 5:15:00"); assertEquals(1, billingSync.doSyncWork(false, now)); assertEquals("-3.12", getDeltaVal(userId, initBalance)); assertEquals("-3.12", billing.getUserBalance(userId).toString()); //но расчет тарифов обновился assertTrue(findBalance(universal, userId).accsBlocked); assertEquals(parseStandartDateTime("01.11.2014 00:00:00"), universal.selectOne(new GetChatAccount(accUid)).tariffLastPay); //старые тарифы не обновили дату оплаты, т.к. она у них позже текущей for(String uid : oldAccs) assertEquals(longFuture, universal.selectOne(new GetChatAccount(uid)).tariffLastPay); //послан запрос на блокировку assertEquals(1, blockReqs.size()); assertTrue(blockReqs.get(0).second); blockReqs.clear(); //не можем менять тарифы юзером pushToSecurityContext(new User(userId)); try { chats.updateAccTariffByUser(accUid, tariffId); fail_exception_expected(); } catch(ChatAccountBlockedException e){ //ok }finally { popUserFromSecurityContext(); } } //юзер закинул мало денег и его не разблочили { assertTrue(findBalance(universal, userId).accsBlocked); Date oldLastPay = universal.selectOne(new GetChatAccount(accUid)).tariffLastPay; Date now = parseStandartDateTime("03.11.2014 13:12:00"); pushToSecurityContext(new User(userId)); try { paypalClient.payAmount = new BigDecimal("3.11"); billing.sendPayReq(paypal_key.strDefVal(), paypalClient.payAmount); billing.paypal_preparePayConfirm(randomSimpleId(), STUB_TOKEN); billing.paypal_finishPayment(now); } finally { popUserFromSecurityContext(); } //баланс изменился, но тариф и блокировка остались прежними assertEquals("-0.01", billing.getUserBalance(userId).toString()); assertTrue(findBalance(universal, userId).accsBlocked); assertEquals(oldLastPay, universal.selectOne(new GetChatAccount(accUid)).tariffLastPay); assertEquals(0, blockReqs.size()); } //юзер пополнил с ассинхронным подверждением и его снова разблокировали { assertTrue(findBalance(universal, userId).accsBlocked); BigDecimal payAmount = new BigDecimal("5.01"); Date prev = parseStandartDateTime("04.11.2014 11:00:00"); Date now = parseStandartDateTime("05.11.2014 13:12:00"); long payId = universal.nextSeqFor(payments); universal.update(new CreatePayment(new PaymentExt(payId, userId, PAYPAL, "somePay", WAIT, prev, prev, payAmount))); paypalClient.payAmount = payAmount; paypalClient.paymentHistory = list(new PaymentBase("somePay", COMPLETED)); paypalClient.paymentId = "somePay"; paypalClient.payment = new PaymentBase(paypalClient.paymentId, COMPLETED); paySync.doSyncWork(now); //платеж прошел assertEquals(COMPLETED, universal.selectOne(new GetPaymentById(payId)).paymentStatus); //акки разблокировались assertEquals("5.00", billing.getUserBalance(userId).toString()); assertFalse(findBalance(universal, userId).accsBlocked); assertEquals(now, universal.selectOne(new GetChatAccount(accUid)).tariffLastPay); //старые тарифы не обновили дату оплаты, т.к. она у них позже текущей for(String uid : oldAccs) assertEquals(longFuture, universal.selectOne(new GetChatAccount(uid)).tariffLastPay); //послан запрос на разблокировку assertEquals(1, blockReqs.size()); assertFalse(blockReqs.get(0).second); blockReqs.clear(); } }finally { popUserFromSecurityContext(); } //Нормируем акки обратно Date now = new Date(); universal.update(new UpdateAllChatAccounts(new TariffStart(now), new TariffLastPay(now))); } private void test_billing_callFromCacheFlag() throws Exception { MailServiceStub mailService = new MailServiceStub(mailSender, props); mailSender.tasks.clear(); Date prevMonth = monthStart(addMonths(new Date(), -1)); BillingSyncService sync = new BillingSyncService(); sync.setCacheServerContext(new CacheServerContext(props, cacheSever, db, mailService)); sync.init(); assertEquals(null, cacheClient.getVal(BILLING_SYNC_REQ)); assertEquals(null, cacheClient.getVal(BILLING_SYNC_RESP)); universal.update(new UpdateChatAccountByUid("demo", new TariffStart(prevMonth),new TariffLastPay(prevMonth))); //call String reqId = "123"; cacheClient.putCache(BILLING_SYNC_REQ, reqId); sync.checkTasksFromCache(); AdminSyncResp resp = tryParseJson(cacheClient.getVal(BILLING_SYNC_RESP), AdminSyncResp.class); assertNotNull(resp); assertEquals(reqId, resp.reqId); assertEquals(1, resp.updatedCount); } private void test_billing_sendErrorsWithEmails() throws Exception { MailServiceStub mailService = new MailServiceStub(mailSender, props); mailSender.tasks.clear(); Date prevMonth = monthStart(addMonths(new Date(), -1)); BillingSyncService sync = new BillingSyncService(); sync.setCacheServerContext(new CacheServerContext(props, cacheSever, db, mailService)); sync.init(); //no errors universal.update(new UpdateChatAccountByUid("demo", new TariffStart(prevMonth),new TariffLastPay(prevMonth))); assertEquals(1, sync.doSyncWork(false)); assertEquals(0, mailSender.tasks.size()); //with errors universal.update(new UpdateChatAccountByUid("demo", new TariffStart(prevMonth),new TariffLastPay(prevMonth))); sync.syncAccsListener = ()-> { throw new TestException(); }; assertEquals(1, sync.doSyncWork(false)); assertEquals(1, mailSender.tasks.size()); } private void test_tariff_billing_concurrent() throws Exception { ExecutorService async = ExecutorsUtil.newSingleThreadExecutor("billing_concurrent"); MailServiceStub mailService = new MailServiceStub(mailSender, props); mailSender.tasks.clear(); //Отключаем все другие акки от апдейта Date longFuture = parseStandartDateTime("02.09.2040 3:00:00"); universal.update(new UpdateAllChatAccounts(new TariffStart(longFuture), new TariffLastPay(longFuture))); pushToSecurityContext_SYSTEM_USER(); try { int tariffId = 2; long userId = userId4; String accUid = "tariff_billing_concurrent"; BigDecimal tariffPrice = new BigDecimal("5.00"); BigDecimal correctVal = new BigDecimal(100); //create acc chats.createAcc(serverId1, accUid, userId, "billing_concurrent", tariffId); chats.setOperatorForAcc(accUid, userId); universal.update(new UpdateUserAccsBlocked(userId, false)); BillingSyncService sync = new BillingSyncService(); sync.setCacheServerContext(new CacheServerContext(props, cacheSever, db, mailService)); sync.init(); //пытаемся менять тариф и в этот момент происходит синх оплаты { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-5.00"; Date pastPay = parseStandartDateTime("01.08.2014 00:00:00"); Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date now = parseStandartDateTime("03.09.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(tariffStart), new TariffLastPay(pastPay))); //race try { chats.updateAccTariff(accUid, 4, new UpdateTariffOps(true, false, tariffStart, pastPay, now, tariffPrice, ()->{ //в транзакции обновления тарифа //создаем новую транзакцию в которой успеваем отработать синхр оплат async.submit(()->{ pushToSecurityContext_SYSTEM_USER(); try { assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); return null; }finally { popUserFromSecurityContext(); } }).get(); })); fail_exception_expected(); }catch(ConcurrentUpdateSqlException e){ //ok } assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //пытаемся синхр оплаты и в этот момент происходит смена тарифа { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-5.34"; Date pastPay = parseStandartDateTime("01.08.2014 00:00:00"); Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date now = parseStandartDateTime("03.09.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(tariffStart), new TariffLastPay(pastPay))); //race int syncCount = sync.doSyncWork(false, now, ()->{ //в транзакции синхр цен //создаем новую транзакцию в которой успеваем обновить тариф async.submit(()->{ pushToSecurityContext_SYSTEM_USER(); try { chats.updateAccTariff(accUid, 4, new UpdateTariffOps(true, false, tariffStart, pastPay, now, tariffPrice)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); return null; }finally { popUserFromSecurityContext(); } }).get(); }); assertEquals(0, syncCount); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов синхра Date newNow = parseStandartDateTime("03.09.2014 4:00:00"); BigDecimal newInitBalance = billing.getUserBalance(userId); assertEquals(0, sync.doSyncWork(false, newNow)); assertEquals("0.00", getDeltaVal(userId, newInitBalance)); } }finally { popUserFromSecurityContext(); } //Нормируем акки обратно Date now = new Date(); universal.update(new UpdateAllChatAccounts(new TariffStart(now), new TariffLastPay(now))); } private void test_billing_monthBill() throws Exception { MailServiceStub mailService = new MailServiceStub(mailSender, props); //Отключаем все другие акки от апдейта Date longFuture = parseStandartDateTime("02.09.2040 3:00:00"); universal.update(new UpdateAllChatAccounts(new TariffStart(longFuture), new TariffLastPay(longFuture))); pushToSecurityContext_SYSTEM_USER(); try { int tariffId = 2; long userId = userId4; String accUid = "billing_monthBill"; BigDecimal correctVal = new BigDecimal(100); //create acc assertEquals(0, chats.getAccsForOperator(userId).size()); chats.createAcc(serverId1, accUid, userId, "test_monthBill", tariffId); assertEquals(1, chats.getAccsForOperator(userId).size()); assertEquals(0, chats.getAccOperators(accUid).size()); //set operator chats.setOperatorForAcc(accUid, userId); assertEquals(1, chats.getAccOperators(accUid).size()); assertEquals("0.00", billing.getUserBalance(userId).toString()); mailSender.tasks.clear(); BillingSyncService sync = new BillingSyncService(); sync.setCacheServerContext(new CacheServerContext(props, cacheSever, db, mailService)); sync.init(); //целый длинный месяц (31) { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-5.00"; Date pastPay = parseStandartDateTime("01.08.2014 00:00:00"); Date now = parseStandartDateTime("02.09.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //целый короткий месяц (28) { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-5.00"; Date pastPay = parseStandartDateTime("01.02.2014 00:00:00"); Date now = parseStandartDateTime("02.03.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //половина длинного месяца { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-2.72"; Date pastPay = parseStandartDateTime("15.08.2014 3:00:00"); Date now = parseStandartDateTime("02.09.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //половина короткого месяца { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-2.24"; Date pastPay = parseStandartDateTime("15.02.2014 3:00:00"); Date now = parseStandartDateTime("20.03.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //успели сменить тариф перед подсчетом { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "0.00"; Date pastPay = parseStandartDateTime("01.03.2014 2:00:00"); Date now = parseStandartDateTime("01.03.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //1,5 месяца (в случае ручного срабатывания синхронизации в середине второго месяца) { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-5.00"; Date pastPay = parseStandartDateTime("01.07.2014 00:00:00"); Date now = parseStandartDateTime("20.08.2014 12:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //2 полных месяца (в случае не срабатывания синхронизации после первого) { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-10.00"; Date pastPay = parseStandartDateTime("01.07.2014 00:00:00"); Date now = parseStandartDateTime("02.09.2014 3:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //3 полных месяца - начинает накапливаться погрешность { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-14.84"; //not 15.00 Date pastPay = parseStandartDateTime("01.07.2014 00:00:00"); Date now = parseStandartDateTime("15.10.2014 11:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //ГОД - большая погрешность { correctBalance(userId, correctVal); BigDecimal initBalance = billing.getUserBalance(userId); String expAmount = "-58.87"; //12*5 = 60 Date pastPay = parseStandartDateTime("01.07.2014 00:00:00"); Date now = parseStandartDateTime("03.07.2015 11:00:00"); universal.update(new UpdateChatAccountByUid(accUid, new TariffStart(pastPay), new TariffLastPay(pastPay))); assertEquals(1, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); //второй вызов -- нет эффекта assertEquals(0, sync.doSyncWork(false, now)); assertEquals(expAmount, getDeltaVal(userId, initBalance)); } //нет ошибок для отправки админу assertEquals(0, mailSender.tasks.size()); //тест рабочего времени таймера { //before assertEquals(-3, sync.doSyncWork(true, parseStandartDateTime("31.08.2014 12:35:00"))); assertEquals(-3, sync.doSyncWork(true, parseStandartDateTime("31.08.2014 23:59:00"))); assertEquals(-2, sync.doSyncWork(true, parseStandartDateTime("01.08.2014 00:00:00"))); assertEquals(-2, sync.doSyncWork(true, parseStandartDateTime("01.08.2014 05:00:00"))); assertEquals(-2, sync.doSyncWork(true, parseStandartDateTime("01.08.2014 05:59:59"))); //in assertEquals(0, sync.doSyncWork(true, parseStandartDateTime("01.08.2014 06:00:00"))); assertEquals(0, sync.doSyncWork(true, parseStandartDateTime("02.08.2014 00:00:00"))); assertEquals(0, sync.doSyncWork(true, parseStandartDateTime("03.08.2014 00:00:00"))); assertEquals(0, sync.doSyncWork(true, parseStandartDateTime("03.08.2014 23:59:00"))); assertEquals(0, sync.doSyncWork(true, parseStandartDateTime("03.08.2014 23:59:01"))); assertEquals(0, sync.doSyncWork(true, parseStandartDateTime("03.08.2014 23:59:59"))); //after assertEquals(-3, sync.doSyncWork(true, parseStandartDateTime("04.08.2014 00:00:00"))); } }finally { popUserFromSecurityContext(); } //Нормируем акки обратно Date now = new Date(); universal.update(new UpdateAllChatAccounts(new TariffStart(now), new TariffLastPay(now))); } private String getDeltaVal(long userId, BigDecimal oldVal) throws Exception{ BigDecimal curBalance = billing.getUserBalance(userId); return getDeltaVal(curBalance, oldVal); } private String getDeltaVal(BigDecimal newVal, BigDecimal oldVal) throws Exception{ return round(newVal.subtract(oldVal)).toString(); } private void correctBalance(long userId, BigDecimal val) throws Exception { universal.update(new UpdateUserBalanceUnsafe(userId, val)); billing.updateUserBalanceCache(userId, false); } private void test_tariff_update_maxInDayLimit() throws Exception { long ownerId = 100; pushToSecurityContext_SYSTEM_USER(); try { //reset day to now chats.updateAccTariff("demo2", 2, true); long t1 = chats.createTariff(new BigDecimal(1), true, 10); long t2 = chats.createTariff(new BigDecimal(2), true, 10); long t3 = chats.createTariff(new BigDecimal(3), true, 10); //day limitations pushToSecurityContext(new User(ownerId)); try { assertEquals(0, chats.getAccsForOperator(ownerId).get(1).tariffChangedInDay); int maxLimitations = PropKey.tariffs_maxChangedInDay.intDefVal(); for (int i = 0; i < maxLimitations; i++) { chats.updateAccTariffByUser("demo2", i%2==0? t1 : t2); assertEquals(i+1, chats.getAccsForOperator(ownerId).get(1).tariffChangedInDay); } try { chats.updateAccTariffByUser("demo2", t3); fail_exception_expected(); }catch(ChangeTariffLimitException e){ //ok } }finally { popUserFromSecurityContext(); } //next day boolean canUseNotPublic = true; boolean checkChangedInDay = true; Date nextDay = addDays(new Date(), 1); chats.updateAccTariff("demo2", t3, new UpdateTariffOps(canUseNotPublic, checkChangedInDay, null, null, nextDay, null)); assertEquals(1, chats.getAccsForOperator(ownerId).get(1).tariffChangedInDay); }finally { popUserFromSecurityContext(); } } private void test_tariff_update() throws Exception { //Нормируем акки под текущю дату Date createDate = parseStandartDateTime("21.08.2014 12:00:00"); universal.update(new UpdateAllChatAccounts(new TariffStart(createDate), new TariffLastPay(createDate))); BigDecimal price = new BigDecimal("5.00"); pushToSecurityContext_SYSTEM_USER(); try { long ownerId = 100; { List<ChatAccount> accs = chats.getAccsForOperator(ownerId); ChatAccount acc = accs.get(0); assertEquals("demo", acc.uid); assertEquals(1L, acc.tariffId); assertEquals(null, acc.tariffPrevId); } //смена спустя минуту { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "0.00"; Date tariffStart = createDate; Date now = new Date(createDate.getTime() + 1000*60); chats.updateAccTariff("demo", 3, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); //test cache update BigDecimal fromCache = tryParseBigDecimal(cacheClient.tryGetVal(getBalanceCacheKey(ownerId)), null); assertEquals(expAmount, getDeltaVal(fromCache, initBalance)); List<ChatAccount> accs = chats.getAccsForOperator(ownerId); ChatAccount acc = accs.get(0); assertEquals("demo", acc.uid); assertEquals(3L, acc.tariffId); assertEquals(Long.valueOf(1L), acc.tariffPrevId); } //смена спустя час { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-0.01"; Date tariffStart = createDate; Date now = new Date(createDate.getTime() + 1000*60*60); chats.updateAccTariff("demo", 2, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); //test cache update BigDecimal fromCache = tryParseBigDecimal(cacheClient.tryGetVal(getBalanceCacheKey(ownerId)), null); assertEquals(expAmount, getDeltaVal(fromCache, initBalance)); } //смена спустя день { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-0.16"; Date tariffStart = createDate; Date now = new Date(createDate.getTime() + 1000*60*60*24); chats.updateAccTariff("demo", 3, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); //test cache update BigDecimal fromCache = tryParseBigDecimal(cacheClient.tryGetVal(getBalanceCacheKey(ownerId)), null); assertEquals(expAmount, getDeltaVal(fromCache, initBalance)); } //смена спустя почти целый месяц { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-4.53"; Date tariffStart = parseStandartDateTime("01.08.2014 10:45:13"); Date now = parseStandartDateTime("29.08.2014 12:15:00"); chats.updateAccTariff("demo", 2, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); //test cache update BigDecimal fromCache = tryParseBigDecimal(cacheClient.tryGetVal(getBalanceCacheKey(ownerId)), null); assertEquals(expAmount, getDeltaVal(fromCache, initBalance)); } //смена спустя целый длинный месяц { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-5.00"; Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date now = parseStandartDateTime("31.08.2014 23:59:59"); chats.updateAccTariff("demo", 3, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); } //смена спустя целый короткий месяц { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-4.52"; Date tariffStart = parseStandartDateTime("01.02.2014 00:00:00"); Date now = parseStandartDateTime("28.02.2014 23:59:59"); chats.updateAccTariff("demo", 2, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); } //смена спустя месяц плюс несколько дней (когда еще не успел отработать синх по оплатам) { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-5.24"; Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date now = parseStandartDateTime("02.09.2014 12:15:00"); chats.updateAccTariff("demo", 3, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); } //смена спустя 2 месяца (сломался синх оплат) { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-10.24"; Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date now = parseStandartDateTime("03.10.2014 12:15:00"); chats.updateAccTariff("demo", 2, new UpdateTariffOps(true, false, tariffStart, tariffStart, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); } //смена спустя день после оплаты прошлого месяца { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-0.24"; Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date lastPay = parseStandartDateTime("01.09.2014 00:00:00"); Date now = parseStandartDateTime("02.09.2014 12:15:00"); chats.updateAccTariff("demo", 3, new UpdateTariffOps(true, false, tariffStart, lastPay, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); } //постановка на паузу в середине месяца делает расчет { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "-0.24"; Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date lastPay = parseStandartDateTime("01.09.2014 00:00:00"); Date now = parseStandartDateTime("02.09.2014 12:15:00"); chats.pauseAcc("demo", new UpdateTariffOps(true, false, tariffStart, lastPay, now, price)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); } //нельзя менять тариф у акка на паузе pushToSecurityContext(new User(ownerId)); try { chats.updateAccTariffByUser("demo", 3); fail_exception_expected(); }catch(ChatAccountPausedException e){ //ok } finally { popUserFromSecurityContext(); } //снятие с паузы не делает расчет { BigDecimal initBalance = billing.getUserBalance(ownerId); String expAmount = "0.00"; Date tariffStart = parseStandartDateTime("01.08.2014 00:00:00"); Date lastPay = parseStandartDateTime("01.09.2014 00:00:00"); Date now = parseStandartDateTime("02.09.2014 12:15:00"); chats.unpauseAcc("demo", 3, new UpdateTariffOps(true, false, tariffStart, lastPay, now, null)); assertEquals(expAmount, getDeltaVal(ownerId, initBalance)); } }finally { popUserFromSecurityContext(); } } private void test_tariff_update_invalidInputs_limitations() throws Exception { pushToSecurityContext_SYSTEM_USER(); try { try { chats.updateAccTariff("demo-nono", 2, false); fail_exception_expected(); }catch(NoChatAccountException e){ //ok } try { chats.updateAccTariff("demo", -99, false); fail_exception_expected(); }catch(TariffNotFoundException e){ //ok } try { chats.updateAccTariff("demo", 6, false); fail_exception_expected(); }catch(NotPublicTariffException e){ //ok } //limitations long storngTariffId = chats.createTariff(ZERO, true, 1); try { chats.updateAccTariff("demo", storngTariffId, false); fail_exception_expected(); }catch(UpdateTariffOperatorsLimitException e){ //ok } }finally { popUserFromSecurityContext(); } } private void test_tariff_defaultTariffs() throws Exception { List<Tariff> tariffs = universal.select(new GetAllTariffs()); assertTrue(tariffs.size() > 1); assertEquals(Tariff.PAUSE_TARIFF_ID, tariffs.get(0).id); assertEquals(0, tariffs.get(0).maxOperators); assertEquals(false, tariffs.get(0).isPublic); assertEquals("0.00", tariffs.get(0).price.toString()); assertEquals(0, tariffs.get(1).maxOperators); assertEquals(false, tariffs.get(1).isPublic); assertEquals(2, tariffs.get(2).maxOperators); assertEquals(true, tariffs.get(2).isPublic); assertEquals(10, tariffs.get(4).maxOperators); assertEquals(false, tariffs.get(4).isPublic); assertEquals(10, tariffs.get(5).maxOperators); assertEquals(true, tariffs.get(5).isPublic); List<Tariff> publicTariffs = chats.getPublicTariffs(); assertEquals(2, publicTariffs.size()); assertEquals(2L, publicTariffs.get(0).id); assertEquals(5L, publicTariffs.get(1).id); } private void test_billing_atomicChangeBalance() throws Exception { long userId = 101L; assertEquals(0, findBalance(universal, userId).balance.intValue()); assertEquals(1, appendBalance(universal, userId, new BigDecimal(1L)).intValue()); assertEquals(1, findBalance(universal, userId).balance.intValue()); assertEquals(2, appendBalance(universal, userId, new BigDecimal(1L)).intValue()); assertEquals(2, findBalance(universal, userId).balance.intValue()); assertEquals(1, appendBalance(universal, userId, new BigDecimal(-1L)).intValue()); assertEquals(1, findBalance(universal, userId).balance.intValue()); //manual check of atomic universal.update(new UpdateUserBalance(userId, new BigDecimal(100), new BigDecimal(99))); assertEquals(1, findBalance(universal, userId).balance.intValue()); universal.update(new UpdateUserBalance(userId, new BigDecimal(1), new BigDecimal(99))); assertEquals(99, findBalance(universal, userId).balance.intValue()); //проверяем, что два конкурентных запроса в разных транзакция //корректно работают с оптимист.блокировкой { ExecutorService singleExecutor = ExecutorsUtil.newSingleThreadExecutor("test-optimistic-lock"); Future<?> f = null; setSingleTxMode(); try { final BigDecimal oldVal = new BigDecimal(99); int updated = universal.updateOne(new UpdateUserBalance(userId, oldVal, new BigDecimal(100))); assertEquals(1, updated); f = singleExecutor.submit(()->{ setSingleTxMode(); try { int updatedInOtherTx = universal.updateOne(new UpdateUserBalance(userId, oldVal, new BigDecimal(98))); assertEquals(0, updatedInOtherTx); }catch (Exception e) { rollbackSingleTx(); throw e; } finally { closeSingleTx(); } return null; }); }catch (Exception e) { rollbackSingleTx(); throw e; } finally { closeSingleTx(); } //если вызвать f.get внутри тела первой tx, то поток 2 зависнет, до тех пор пока не будет коммит потока 1 (дед лок) //если в потоке 2 будет userId+1, то зависания не будет //заморозку делает сама БД, проверено под дебагом: если до коммита потока 1 в клиенте к бд вызвать апдейт, то он зависнет f.get(); //в итоге прав оказался первый поток assertEquals(100, findBalance(universal, userId).balance.intValue()); singleExecutor.shutdown(); } } private void test_billing_payBill() throws Exception { pushToSecurityContext_SYSTEM_USER(); try { BigDecimal balance = billing.getUserBalance(userId1); List<PaymentExt> payments = billing.getPayments(userId1, 100, 0); String desc = "test bill"; BigDecimal delta = TEN; billing.payBill(userId1, delta, new Date(), SYSTEM_OUT_CORRECTION, desc); BigDecimal newBalance = billing.getUserBalance(userId1); assertEquals(balance.subtract(TEN).doubleValue(), newBalance.doubleValue(), 0.01); List<PaymentExt> newPayments = billing.getPayments(userId1, 100, 0); assertEquals(payments.size()+1, newPayments.size()); PaymentExt item = newPayments.get(0); assertEquals(desc, item.details); assertEquals(PaymentType.SYSTEM_OUT_CORRECTION, item.payType); }finally { popUserFromSecurityContext(); } } private void test_billing_paySync() throws Exception { MapProps props = new MapProps(); props.putVal(admin_Emails, "some@host"); props.putVal(paypal_sync_debug_DisableTimer, true); props.putVal(mail_storeToDisc, false); MailServiceStub mailService = new MailServiceStub(mailSender, props); PaypalClientStub clientStub = new PaypalClientStub(); ArrayList<PaymentExt> syncPaymentsByDate = new ArrayList<PaymentExt>(); ArrayList<PaymentExt> syncPaymentsById = new ArrayList<PaymentExt>(); boolean[] canSync = {false}; //service PaypalPaymentsSynchService syncService = new PaypalPaymentsSynchService(){ @Override protected void syncPaymentsByDate(List<PaymentExt> list, Date now) { syncPaymentsByDate.clear(); syncPaymentsByDate.addAll(list); if(canSync[0]) super.syncPaymentsByDate(list, now); } @Override protected void syncPaymentsByIdAsync(List<PaymentExt> list, Date now) { syncPaymentsById.clear(); syncPaymentsById.addAll(list); if(canSync[0]) super.syncPaymentsByIdAsync(list, now); } }; syncService.setCacheServerContext(new CacheServerContext(props, cacheSever, db, mailService)); syncService.setClient(clientStub); syncService.init(); Date now = new Date(); Date minuteAgo = new Date(now.getTime() - DateUtil.ONE_MINUTE); Date twoHoursAgo = new Date(now.getTime() - DateUtil.ONE_HOUR*2); Date monthAgo = DateUtil.addDays(now, -31); long userId = 103L; //fill db universal.update(new CreatePayment(new PaymentExt(universal.nextSeqFor(payments), userId, PAYPAL, "p1", WAIT, minuteAgo, minuteAgo, BigDecimal.ONE))); universal.update(new CreatePayment(new PaymentExt(universal.nextSeqFor(payments), userId, PAYPAL, "p2", WAIT, twoHoursAgo, twoHoursAgo, BigDecimal.ONE))); universal.update(new CreatePayment(new PaymentExt(universal.nextSeqFor(payments), userId, PAYPAL, "p3", WAIT, monthAgo, monthAgo, BigDecimal.ONE))); //check filter logic pushToSecurityContext_SYSTEM_USER(); try { assertEquals(0, billing.getUserBalance(userId).intValue()); //first call -- all payments to sync { syncService.doSyncWork(now); assertEquals(2, syncPaymentsByDate.size()); assertEquals(1, syncPaymentsById.size()); assertEquals("p1", syncPaymentsByDate.get(0).externalId); assertEquals("p2", syncPaymentsByDate.get(1).externalId); assertEquals("p3", syncPaymentsById.get(0).externalId); syncPaymentsByDate.clear(); syncPaymentsById.clear(); } //second call -- only new now = new Date(now.getTime() + 1000); { syncService.doSyncWork(now); assertEquals(1, syncPaymentsByDate.size()); assertEquals(0, syncPaymentsById.size()); assertEquals("p1", syncPaymentsByDate.get(0).externalId); syncPaymentsByDate.clear(); syncPaymentsById.clear(); } //next call -- same now = new Date(now.getTime() + 1000); { syncService.doSyncWork(now); assertEquals(1, syncPaymentsByDate.size()); assertEquals(0, syncPaymentsById.size()); assertEquals("p1", syncPaymentsByDate.get(0).externalId); syncPaymentsByDate.clear(); syncPaymentsById.clear(); } //after long delta -- all now = new Date(now.getTime() + 1000); props.putVal(paypal_sync_longUpdateDelta, 0); { syncService.doSyncWork(now); assertEquals(2, syncPaymentsByDate.size()); assertEquals(1, syncPaymentsById.size()); syncPaymentsByDate.clear(); syncPaymentsById.clear(); } now = new Date(now.getTime() + 1000); props.putVal(paypal_sync_longUpdateDelta, paypal_sync_longUpdateDelta.longDefVal()); { syncService.doSyncWork(now); assertEquals(1, syncPaymentsByDate.size()); assertEquals(0, syncPaymentsById.size()); assertEquals("p1", syncPaymentsByDate.get(0).externalId); syncPaymentsByDate.clear(); syncPaymentsById.clear(); } }finally { popUserFromSecurityContext(); } //sync by pushToSecurityContext_SYSTEM_USER(); try { canSync[0] = true; //update by date now = new Date(now.getTime() + 1000); assertEquals(WAIT, universal.selectOne(new GetPaymentByExternalId(PAYPAL, "p1")).paymentStatus); clientStub.paymentHistory = list(new PaymentBase("p1", COMPLETED)); syncService.doSyncWork(now); assertEquals(COMPLETED, universal.selectOne(new GetPaymentByExternalId(PAYPAL, "p1")).paymentStatus); assertEquals(1, universal.selectOne(new SelectUserBalanceById(userId)).balance.intValue()); assertEquals(1, billing.getUserBalance(userId).intValue()); //update by ids now = new Date(now.getTime() + 1000); props.putVal(paypal_sync_longUpdateDelta, 0); clientStub.paymentHistory = list(new PaymentBase("p2", COMPLETED)); clientStub.paymentId = "p3"; clientStub.payment = new PaymentBase(clientStub.paymentId, COMPLETED); syncService.doSyncWork(now); assertEquals(COMPLETED, universal.selectOne(new GetPaymentByExternalId(PAYPAL, "p2")).paymentStatus); assertEquals(COMPLETED, universal.selectOne(new GetPaymentByExternalId(PAYPAL, "p3")).paymentStatus); assertEquals(3, billing.getUserBalance(userId).intValue()); now = new Date(now.getTime() + 1000); syncPaymentsByDate.clear(); syncPaymentsById.clear(); syncService.doSyncWork(now); assertEquals(0, syncPaymentsByDate.size()); assertEquals(0, syncPaymentsById.size()); }finally { popUserFromSecurityContext(); } //test timers props.putVal(paypal_sync_debug_DisableTimer, false); props.putVal(paypal_sync_timerDelay, 1L); props.putVal(paypal_sync_timerDelta, 20L); syncService.stop(); syncService.init(); pushToSecurityContext_SYSTEM_USER(); try { canSync[0] = true; clientStub.paymentHistory = list(new PaymentBase("p4", COMPLETED)); universal.update(new CreatePayment(new PaymentExt(universal.nextSeqFor(payments), userId, PAYPAL, "p4", WAIT, minuteAgo, minuteAgo, BigDecimal.ONE))); Thread.sleep(50); assertEquals(COMPLETED, universal.selectOne(new GetPaymentByExternalId(PAYPAL, "p4")).paymentStatus); assertEquals(4, billing.getUserBalance(userId).intValue()); }finally { syncService.stop(); popUserFromSecurityContext(); } //test send errors to admin props.putVal(paypal_sync_sendErrorsDelay, 1L); props.putVal(paypal_sync_sendErrorsDelta, 20L); syncService.init(); try { universal.update(new CreatePayment(new PaymentExt(universal.nextSeqFor(payments), userId, PAYPAL, "p5", WAIT, minuteAgo, minuteAgo, BigDecimal.ONE))); mailSender.tasks.clear(); clientStub.paymentHistory = null; Thread.sleep(100); assertTrue(mailSender.tasks.size() > 0); //dissable send errors props.putVal(paypal_sync_debug_DisableSendErrors, true); Thread.sleep(50); mailSender.tasks.clear(); Thread.sleep(50); assertTrue(mailSender.tasks.size() == 0); //enable again props.putVal(paypal_sync_debug_DisableSendErrors, false); Thread.sleep(50); assertTrue(mailSender.tasks.size() > 0); //set filter props.putVal(paypal_sync_skipErrorTerms, "empty history by daysBefore"); Thread.sleep(50); mailSender.tasks.clear(); Thread.sleep(50); assertTrue(mailSender.tasks.size() == 0); //remove filter props.putVal(paypal_sync_skipErrorTerms, (String)null); Thread.sleep(50); assertTrue(mailSender.tasks.size() > 0); }finally { syncService.stop(); } } private void test_billing_paypal_paySteps() throws Exception { User user = new User(100, "some", "dd@dd.dd", ACTIVATED); pushToSecurityContext(user); try { //show paypal page { assertNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); PayData data = billing.sendPayReq(paypal_key.strDefVal(), new BigDecimal(12)); assertNotNull(data); assertNotNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); } //paypal wrong resp try { billing.paypal_preparePayConfirm("some", STUB_TOKEN+"123"); }catch(NoDataToConfirmPaymentException e){ //ok } //paypal resp { assertNull(cacheClient.getVal(BillingService.getConfirmPayCacheKey(user.id))); String userPayId = "some-"+randomSimpleId(); billing.paypal_preparePayConfirm(userPayId, STUB_TOKEN); assertNotNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); } //confirm pay { mailSender.tasks.clear(); assertEquals(0, billing.getCurUserBalance().intValue()); billing.paypal_finishPayment(); lastFrom(asyncFutures).get(); assertTrue(billing.getCurUserBalance().intValue() > 0); assertNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); assertNull(cacheClient.getVal(BillingService.getConfirmPayCacheKey(user.id))); //check db List<PaymentExt> payments = billing.getPayments(10, 0); assertEquals(1, payments.size()); //check email sended assertEquals(1, mailSender.tasks.size()); } } finally { popUserFromSecurityContext(); } } private void test_billing_2checkout_paySteps() throws Exception { User user = new User(100, "some", "dd@dd.dd", ACTIVATED); pushToSecurityContext(user); try { int initBalance = billing.getCurUserBalance().intValue(); int payCount = 12; String token = null; //pay req { assertNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); PayData data = billing.sendPayReq(toCheckout_key.strDefVal(), new BigDecimal(payCount)); assertNotNull(data); assertNotNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); token = data.token; } //wrong resp try { billing.tochekout_finishPayment("some", "some"); }catch(NoDataToConfirmPaymentException e){ //ok } //confirm pay { assertNotNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); mailSender.tasks.clear(); assertEquals(initBalance, billing.getCurUserBalance().intValue()); String txId = "some-"+randomSimpleId(); billing.tochekout_finishPayment(token, txId); lastFrom(asyncFutures).get(); assertEquals(initBalance + payCount, billing.getCurUserBalance().intValue()); assertNull(cacheClient.getVal(BillingService.getPayReqCacheKey(user.id))); assertNull(cacheClient.getVal(BillingService.getConfirmPayCacheKey(user.id))); //check db List<PaymentExt> payments = billing.getPayments(10, 0); assertEquals(2, payments.size()); PaymentExt payment = payments.get(0); assertEquals(payCount, payment.amount.intValue()); assertEquals(txId, payment.externalId); assertEquals(PaymentStatus.COMPLETED, payment.paymentStatus); assertEquals(PaymentType.REPLENISHMENT, payment.payType); assertEquals(PaymentProvider.TO_CHECKOUT, payment.provider); //check email sended assertEquals(1, mailSender.tasks.size()); } } finally { popUserFromSecurityContext(); } } private void test_billing_get_balance_from_cache_or_db() throws Exception { pushToSecurityContext_SYSTEM_USER(); try { //from cache { long user = 100; assertEquals("0.00", cacheClient.getVal("balance-"+user)); assertEquals("0.00", billing.getUserBalance(user).toString()); } //from db and put to cache { long user = 102; assertEquals(null, cacheClient.getVal("balance-"+user)); assertEquals(0, billing.getUserBalance(user).intValue()); lastFrom(asyncFutures).get(); assertEquals("0.00", cacheClient.getVal("balance-"+user)); } //unknown user try { billing.getUserBalance(-99); fail_exception_expected(); }catch(UserNotFoundException e){ //ok } }finally { popUserFromSecurityContext(); } } private void test_billing_put_balances_to_cache() throws Exception { long user1 = 100; long user2 = 101; //in start assertEquals("0.00", cacheClient.getVal("balance-"+user1)); assertEquals(null, cacheClient.getVal("balance-"+user2)); //after creation pushToSecurityContext_SYSTEM_USER(); try { String accountId = "demo-balance"; chats.createAcc(serverId3, accountId, user2, null, 1); }finally { popUserFromSecurityContext(); } lastFrom(asyncFutures).get(); assertEquals(null, cacheClient.getVal("balance-"+user2)); } private void test_chats_operatorsLimits() throws Exception { long tariffId = 2; String name = "operatorsLimits"; User user = new User(userId1); pushToSecurityContext(user); try { String accUid = chats.createAccByUser(name, tariffId); chats.setOperatorForAcc(accUid, userId1); chats.setOperatorForAcc(accUid, userId2); //ограничение тарифа на макс число операторов try { chats.setOperatorForAcc(accUid, userId3); fail_exception_expected(); }catch(OperatorsLimitException e){ //ok } chats.removeUserPrivileges(accUid, userId2, set(PrivilegeType.CHAT_OPERATOR)); chats.setOperatorForAcc(accUid, userId3); //ограничение тарифа на макс число операторов снова try { chats.setOperatorForAcc(accUid, userId2); fail_exception_expected(); }catch(OperatorsLimitException e){ //ok } //ограничение при паузе { chats.removeUserPrivileges(accUid, userId3, set(PrivilegeType.CHAT_OPERATOR)); chats.pauseAccByUser(accUid); try { chats.setOperatorForAcc(accUid, userId2); fail_exception_expected(); }catch(ChatAccountPausedException e){ //ok } chats.unpauseAccByUser(accUid); chats.setOperatorForAcc(accUid, userId2); } }finally { popUserFromSecurityContext(); } } private void test_chats_changePrivsForUser() throws Exception { long tariffId = 5; User user1 = new User(userId1); User user2 = new User(userId2); String name = "changePrivsForUser"; String accUid = null; //create acc pushToSecurityContext(user1); try { accUid = chats.createAccByUser(name, tariffId); }finally { popUserFromSecurityContext(); } assertEquals(set(CHAT_OWNER), chats.getAccPrivilegesForUser(accUid, userId1)); //add empty privs { chats.addUserPrivileges(accUid, userId2, set()); assertEquals(set(), chats.getAccPrivilegesForUser(accUid, userId2)); } //add with no role { try { chats.addUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); fail_exception_expected(); }catch(AccessDeniedException e){ //ok } } //add with wrong role { pushToSecurityContext(user2); try { chats.addUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); fail_exception_expected(); }catch(AccessDeniedException e){ //ok } finally { popUserFromSecurityContext(); } } //add like owner { pushToSecurityContext(user1); try { chats.addUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); }finally { popUserFromSecurityContext(); } assertEquals(set(CHAT_OPERATOR), chats.getAccPrivilegesForUser(accUid, userId2)); } //remove empty privs { chats.removeUserPrivileges(accUid, userId2, set()); assertEquals(set(CHAT_OPERATOR), chats.getAccPrivilegesForUser(accUid, userId2)); } //remove with no role { try { chats.removeUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); fail_exception_expected(); }catch(AccessDeniedException e){ //ok } } //remove with wrong role { pushToSecurityContext(user2); try { chats.removeUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); fail_exception_expected(); }catch(AccessDeniedException e){ //ok } finally { popUserFromSecurityContext(); } } //remove like owner { pushToSecurityContext(user1); try { chats.removeUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); }finally { popUserFromSecurityContext(); } assertEquals(set(), chats.getAccPrivilegesForUser(accUid, userId2)); } //add moder and self operator { pushToSecurityContext(user1); try { chats.addUserPrivileges(accUid, userId1, set(CHAT_OPERATOR)); chats.addUserPrivileges(accUid, userId2, set(CHAT_MODER)); }finally { popUserFromSecurityContext(); } assertEquals(set(CHAT_OWNER, CHAT_OPERATOR), chats.getAccPrivilegesForUser(accUid, userId1)); assertEquals(set(CHAT_MODER), chats.getAccPrivilegesForUser(accUid, userId2)); } //try add moder by other moder { pushToSecurityContext(user2); try { chats.addUserPrivileges(accUid, userId3, set(CHAT_MODER)); fail_exception_expected(); }catch(AccessDeniedException e){ //ok } finally { popUserFromSecurityContext(); } } //try remove moder by other moder { pushToSecurityContext(user2); try { chats.removeUserPrivileges(accUid, userId2, set(CHAT_MODER)); fail_exception_expected(); }catch(AccessDeniedException e){ //ok } finally { popUserFromSecurityContext(); } } //add operator by moder { pushToSecurityContext(user2); try { chats.addUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); chats.addUserPrivileges(accUid, userId3, set(CHAT_OPERATOR)); } finally { popUserFromSecurityContext(); } assertEquals(set(CHAT_MODER, CHAT_OPERATOR), chats.getAccPrivilegesForUser(accUid, userId2)); assertEquals(set(CHAT_OPERATOR), chats.getAccPrivilegesForUser(accUid, userId3)); } //remove operator by moder { pushToSecurityContext(user2); try { chats.removeUserPrivileges(accUid, userId2, set(CHAT_OPERATOR)); chats.removeUserPrivileges(accUid, userId3, set(CHAT_OPERATOR)); } finally { popUserFromSecurityContext(); } assertEquals(set(CHAT_MODER), chats.getAccPrivilegesForUser(accUid, userId2)); assertEquals(set(), chats.getAccPrivilegesForUser(accUid, userId3)); } //add op with unexists user pushToSecurityContext(user2); try { chats.addUserPrivileges(accUid, -100, set(CHAT_OPERATOR)); } finally { popUserFromSecurityContext(); } } private void test_chats_renameAccs_BySystem_ByUser() throws Exception { int userId = 100; String uid = null; pushToSecurityContext_SYSTEM_USER(); try { List<ChatAccount> accs = chats.getAccsForOperator(userId); assertTrue(accs.size() > 0); uid = accs.get(0).uid; }finally { popUserFromSecurityContext(); } //rename by system String newNameA = "newName-123"; pushToSecurityContext_SYSTEM_USER(); try { chats.putAccConfigByUser(uid, Key.name, newNameA); assertEquals(newNameA, chats.getAccsForOperator(userId).get(0).name); }finally { popUserFromSecurityContext(); } //rename by user String newNameB = "newName-345"; pushToSecurityContext(new User(100)); try { chats.putAccConfigByUser(uid, Key.name, newNameB); assertEquals(newNameB, chats.getAccsForOperator(userId).get(0).name); }finally { popUserFromSecurityContext(); } } private void test_chats_createAccs_byUser() throws Exception { pushToSecurityContext_SYSTEM_USER(); try { List<ServerRow> servers = chats.getServers(); assertEquals(3, servers.size()); String accName = "test_chats_createAccs_byUser"; User user = new User(100); //create by System try { chats.createAccByUser(accName); fail_exception_expected(); }catch(UserNotFoundException e){ //ok } //no servers exception { for (ServerRow server : servers) chats.setServerFull(server.id, true); pushToSecurityContext(user); try { chats.createAccByUser(accName); fail_exception_expected(); }catch(NoAvailableServerException e){ //ok }finally { popUserFromSecurityContext(); } } //set server to acc long serverId = servers.get(1).id; chats.setServerFull(serverId, false); pushToSecurityContext(user); try { chats.createAccByUser(accName); }finally { popUserFromSecurityContext(); } List<ChatAccount> accs = chats.getAccsForOperator(user.id); ChatAccount acc = find(accs, (c) -> accName.equals(c.name)); assertNotNull(acc); assertNotNull(acc.created); }finally { popUserFromSecurityContext(); } } private void test_chats_createServerAndAcc_BySystem() throws Exception { mailSender.tasks.clear(); pushToSecurityContext_SYSTEM_USER(); try { //dublicate try { chats.createServer(server1HttpUrl, server1HttpsUrl); fail_exception_expected(); }catch(SQLException e){ //ok } assertEquals(0, mailSender.tasks.size()); serverId3 = chats.createServer(server3HttpUrl, server3HttpsUrl); int chatOwnerId = 100; //dublicate try { chats.createAcc(serverId3, "demo", chatOwnerId, null, 1); fail_exception_expected(); }catch(SQLException e){ //ok } assertEquals(0, mailSender.tasks.size()); String accountId = "demo3"; chats.createAcc(serverId3, accountId, chatOwnerId, null, 1); assertEquals(1, mailSender.tasks.size()); int chatOperatorId = 2; chats.setOperatorForAcc(accountId, chatOperatorId); //test get ServerRow server = chats.getServerByAcc(accountId); assertNotNull(server); assertEquals(server3HttpUrl, server.httpUrl); }finally { popUserFromSecurityContext(); } } private void test_set_get_roles() throws Exception { try { pushToSecurityContext_SYSTEM_USER(); assertEquals(emptySet(), users.getUserById(userId1).getRoles()); users.setRoles(userId1, set(ADMIN, MODERATOR)); assertEquals(set(ADMIN, MODERATOR), users.getUserById(userId1).getRoles()); users.setRoles(userId1, set(ADMIN)); assertEquals(set(ADMIN), users.getUserById(userId1).getRoles()); users.setRoles(userId1, new HashSet<UserRole>(0)); assertEquals(emptySet(), users.getUserById(userId1).getRoles()); users.setRoles(userId1, null); assertEquals(emptySet(), users.getUserById(userId1).getRoles()); }finally { popUserFromSecurityContext(); } } private void test_ban_user_runtime_with_exists_session() throws Exception { LoginUserReq loginReq = new LoginUserReq(mail1, psw1, false); //login security.createUserSession(req, resp, loginReq); { User user = security.getUserFromSession(req); assertNotNull(user); assertEquals(login1, user.login); } //ban try { pushToSecurityContext_SYSTEM_USER(); users.banUser(userId1); } finally { popUserFromSecurityContext(); } assertNull(security.getUserFromSession(req)); //unban try { pushToSecurityContext_SYSTEM_USER(); users.activateUser(userId1); } finally { popUserFromSecurityContext(); } { User user = security.getUserFromSession(req); assertNotNull(user); assertEquals(login1, user.login); } //ban and try login try { pushToSecurityContext_SYSTEM_USER(); users.banUser(userId1); } finally { popUserFromSecurityContext(); } assertNull(security.getUserFromSession(req)); req.clearSessionAttrs(); try { security.createUserSession(req, resp, loginReq); fail_exception_expected(); }catch (BannedUserException e) { //ok } assertNull(security.getUserFromSession(req)); //unban and login try { pushToSecurityContext_SYSTEM_USER(); users.activateUser(userId1); } finally { popUserFromSecurityContext(); } security.createUserSession(req, resp, loginReq); assertNotNull(security.getUserFromSession(req)); } private void test_invalidLoginsCount() throws Exception { String login = "test"; LoginUserReq data = new LoginUserReq(login, "123", false); String cacheKey = getInvalidLoginsKey(req, data); //init state assertEquals(0, security.getInvalidLoginsCount(req, data, 100)); assertNull(cacheClient.getVal(cacheKey)); //put-get security.setInvalidLoginsCountAsync(req, data, 3).get(); assertEquals(3, security.getInvalidLoginsCount(req, data, 100)); assertEquals("3",cacheClient.getVal(cacheKey)); assertEquals(INVALID_LOGINS_CACHE_LIVETIME_MS, cacheSever.getItemLivetime(cacheKey).intValue()); //remove security.setInvalidLoginsCountAsync(req, data, 0).get(); assertEquals(0, security.getInvalidLoginsCount(req, data, 100)); assertNull(cacheClient.getVal(cacheKey)); } private void test_remMeToken_maxCount() throws Exception { int maxRemCount = security.maxRemCount(); int deleteRemCount = security.deleteRemCount(); for (int i = 0; i < maxRemCount + deleteRemCount; i++) { resetWeb(); security.createUserSession(req, resp, new LoginUserReq(mail4, psw4, true)); asyncFutures.get(0).get(); } List<RemToken> stored = db.universal.select(new SelectRemTokensByUser(userId4)); assertEquals(maxRemCount-deleteRemCount, stored.size()); } private void test_user_psw_secure() throws Exception { UserExt stored = db.universal.selectOne(new SelectUserById(userId1)); assertEquals(stored.pswHash, WebUtil.getHash(psw1, stored.pswSalt)); } private void test_remMeToken_secure() throws Exception { //login resetWeb(); security.createUserSession(req, resp, new LoginUserReq(mail2, psw2, true)); asyncFutures.get(0).get(); ClientRemToken clientToken = ClientRemToken.decodeFromCookieVal(resp.cookies.get(0).getValue()); //check db secure List<RemToken> stored = db.universal.select(new SelectRemTokensByUser(userId2)); RemToken storedToken = stored.get(0); assertEquals(storedToken.tokenHash, WebUtil.getHash(clientToken.random, storedToken.tokenSalt)); } private void test_create_without_remMe() throws Exception { resetWeb(); //login security.createUserSession(req, resp, new LoginUserReq(mail1, psw1, true)); asyncFutures.get(0).get(); //clear session and login again with FALSE flag req.clearSessionAttrs(); req.setCookies(resp); resp.clearCookies(); security.createUserSession(req, resp, new LoginUserReq(mail1, psw1, false)); assertEmptyRemCookie(); } private void test_logout_remMe() throws Exception { resetWeb(); //login security.createUserSession(req, resp, new LoginUserReq(mail1, psw1, true)); asyncFutures.get(0).get(); assertNotNull(req.session.getAttribute(SESSION_OBJ_KEY)); Cookie cookie1 = resp.cookies.get(0); //logout with no cookie in req req.clearCookies(); resp.clearCookies(); security.logout(req, resp); assertNull(req.session.getAttribute(SESSION_OBJ_KEY)); assertEmptyRemCookie(); //restore req.setCookies(cookie1); security.restoreUserSession(req, resp); assertNotNull(req.session.getAttribute(SESSION_OBJ_KEY)); //logout with cookie in req req.setCookies(cookie1); resp.clearCookies(); security.logout(req, resp); assertNull(req.session.getAttribute(SESSION_OBJ_KEY)); assertEmptyRemCookie(); } private void test_create_restore_remMe() throws Exception { resetWeb(); //try restore with no cookie assertNull(security.restoreUserSession(req, resp)); //first login asyncFutures.clear(); security.createUserSession(req, resp, new LoginUserReq(mail1, psw1, true)); asyncFutures.get(0).get(); assertNotNull(req.session.getAttribute(SESSION_OBJ_KEY)); assertEquals(1, resp.cookies.size()); Cookie cookie1 = resp.cookies.get(0); assertEquals(REM_TOKEN, cookie1.getName()); //try restore with full session and NO cookie assertNull(security.restoreUserSession(req, resp)); //try restore with empty session and NO cookie req.clearSessionAttrs(); assertNull(security.restoreUserSession(req, resp)); //restore session with cookie asyncFutures.clear(); req.clearSessionAttrs(); req.setCookies(cookie1); resp.clearCookies(); assertNotNull(security.restoreUserSession(req, resp)); assertNotNull(req.session.getAttribute(SESSION_OBJ_KEY)); asyncFutures.get(0).get(); //after restored it has new cookie assertEquals(1, resp.cookies.size()); Cookie cookie_AfterResore = resp.cookies.get(0); //try restore with old cookie req.clearSessionAttrs(); req.clearCookies(); req.setCookies(cookie1); resp.clearCookies(); assertNull(security.restoreUserSession(req, resp)); //restore with new cookie req.clearCookies(); req.setCookies(cookie_AfterResore); resp.clearCookies(); assertNotNull(security.restoreUserSession(req, resp)); asyncFutures.get(0).get(); cookie1 = resp.cookies.get(0); //create agian with exists session assertNotNull(req.session.getAttribute(SESSION_OBJ_KEY)); try { security.createUserSession(req, resp, new LoginUserReq(login1, psw1, true)); fail_exception_expected(); }catch (UserSessionAlreadyExistsException e) { //ok } //create again with clear inputs //it will be TWO tokens in DB asyncFutures.clear(); req.clearSessionAttrs(); req.clearCookies(); resp.clearCookies(); security.createUserSession(req, resp, new LoginUserReq(mail1, psw1, true)); asyncFutures.get(0).get(); Cookie cookie2 = resp.cookies.get(0); assertFalse(cookie1.getValue().equals(cookie2.getValue())); // try to restore with old cookie req.clearSessionAttrs(); req.setCookies(cookie1); assertNotNull(security.restoreUserSession(req, resp)); // restore with new cookie req.setCookies(cookie2); req.clearSessionAttrs(); assertNotNull(security.restoreUserSession(req, resp)); } private void test_user_update() throws Exception { pushToSecurityContext_SYSTEM_USER(); try { //correct String newMail = "new@mail.com"; String newLogin = "'; and 1=1; newUser"; String newPsw = "newPsw"; users.updateUser(userId1, psw1, new UpdateUserReq(newMail, newLogin, newPsw)); User updated = users.getUserById(userId1); assertEquals(newMail, updated.email); assertEquals(newLogin, updated.login); assertNotNull(users.checkEmailOrLoginAndPsw(newMail, newPsw)); users.updateUser(userId1, newPsw, new UpdateUserReq(mail1, login1, psw1)); updated = users.getUserById(userId1); assertEquals(mail1, updated.email); assertEquals(login1, updated.login); assertNotNull(users.checkEmailOrLoginAndPsw(mail1, psw1)); //wrong psw try { users.updateUser(userId1, null, new UpdateUserReq(newMail, newLogin, newPsw)); fail_exception_expected(); }catch (ValidationException e) { //ok } try { users.updateUser(userId1, psw2, new UpdateUserReq(newMail, newLogin, newPsw)); fail_exception_expected(); }catch (InvalidLoginDataForUpdateException e) { //ok } //wrong login try { users.updateUser(userId1, psw1, new UpdateUserReq(newMail, User.INVALID_LOGIN_CHARS, newPsw)); fail_exception_expected(); }catch (ValidationException e) { //ok } //wrong email try { users.updateUser(userId1, psw1, new UpdateUserReq("wrongMail", newLogin, newPsw)); fail_exception_expected(); }catch (ValidationException e) { //ok } } finally { popUserFromSecurityContext(); } } private void test_user_change_psw() throws Exception { mailSender.tasks.clear(); //for exists assertNotNull(users.checkEmailOrLoginAndPsw(mail3, psw3)); assertNotNull(users.checkEmailOrLoginAndPsw(login3, psw3)); users.generateNewPassword(mail3); assertNull(users.checkEmailOrLoginAndPsw(mail3, psw3)); assertNull(users.checkEmailOrLoginAndPsw(login3, psw3)); RestorePswEmailParser fromEmail = new RestorePswEmailParser(mailSender.tasks.get(0).msg.text); assertEquals(login3, fromEmail.login); assertNotNull(users.checkEmailOrLoginAndPsw(mail3, fromEmail.psw)); //by login users.generateNewPassword(login3); assertEquals(1, mailSender.tasks.size()); //by unknown users.generateNewPassword("unknown data"); assertEquals(1, mailSender.tasks.size()); } private void test_user_send_activation_email_again() throws Exception { try { pushToSecurityContext_SYSTEM_USER(); users.sendActivationEmailAgain(mail4+"123"); assertEquals(4, mailSender.tasks.size()); users.sendActivationEmailAgain(mail3); assertEquals(4, mailSender.tasks.size()); props.putVal(users_expiredTime, -1); try { users.sendActivationEmailAgain(mail4); fail_exception_expected(); }catch (UserActivationExpiredException e) { //ok } props.removeVal(users_expiredTime); users.sendActivationEmailAgain(mail4); assertEquals(5, mailSender.tasks.size()); ActivationEmailParser fromEmail = new ActivationEmailParser(mailSender.tasks.get(4).msg.text); users.activateUser(fromEmail.email, fromEmail.code); assertNotNull(users.checkEmailOrLoginAndPsw(mail4, psw4)); }finally { popUserFromSecurityContext(); } } private void test_user_invalid_activation_states() throws Exception { ActivationEmailParser fromEmail = new ActivationEmailParser(mailSender.tasks.get(2).msg.text); users.activateUser(fromEmail.email+"123", fromEmail.code); checkNotActiveUser(users, login3, mail3, psw3); try { users.activateUser(fromEmail.email, fromEmail.code+"123"); fail_exception_expected(); }catch (InvalidUserActivationCodeException e) { //ok } props.putVal(users_expiredTime, -1); try { users.activateUser(fromEmail.email, fromEmail.code); fail_exception_expected(); }catch (UserActivationExpiredException e) { //ok } props.removeVal(users_expiredTime); users.activateUser(fromEmail.email, fromEmail.code); assertNotNull(users.checkEmailOrLoginAndPsw(mail3, psw3)); } private void test_user_activate_from_email_text() throws Exception { checkNotActiveUser(users, login2, mail2, psw2); ActivationEmailParser fromEmail = new ActivationEmailParser(mailSender.tasks.get(1).msg.text); users.activateUser(fromEmail.email, fromEmail.code); assertNotNull(users.checkEmailOrLoginAndPsw(mail2, psw2)); assertNotNull(users.checkEmailOrLoginAndPsw(login2, psw2)); //second activation users.activateUser(fromEmail.email, fromEmail.code); } private void test_user_unban() throws Exception { try { pushToSecurityContext_SYSTEM_USER(); users.activateUser(userId1); assertNotNull(users.checkEmailOrLoginAndPsw(mail1, psw1)); }finally { popUserFromSecurityContext(); } } private void test_user_ban() throws Exception { try { pushToSecurityContext_SYSTEM_USER(); users.banUser(userId1); try { users.checkEmailOrLoginAndPsw(mail1, psw1); fail_exception_expected(); }catch (BannedUserException e) { //ok } try { users.checkEmailOrLoginAndPsw(login1, psw1); fail_exception_expected(); }catch (BannedUserException e) { //ok } //try ban ADMIN user try { users.banUser(100); fail_exception_expected(); }catch (UnmodifiableAdminUserException e) { //ok } }finally { popUserFromSecurityContext(); } } private void test_user_activate() throws Exception { test_user_unban(); assertNull(users.checkEmailOrLoginAndPsw(mail1, psw2)); assertNull(users.checkEmailOrLoginAndPsw(login1, psw2)); } private void test_user_unexists() throws Exception { assertNull(users.checkEmailOrLoginAndPsw("unknown", "unknown")); checkNotActiveUser(users, login1, mail1, psw2); } private void test_user_invalid_inputs() throws Exception { createUserWithInvalidData(mail1, "login@", psw1, users); createUserWithInvalidData(mail1, "login<", psw1, users); createUserWithInvalidData(mail1, "login&", psw1, users); createUserWithInvalidData(mail1, "login#", psw1, users); createUserWithInvalidData("new-"+login2, "invalid-email", psw1, users); } private void test_user_duplicates() throws Exception { try { users.createUser(new User(login1, "new-"+mail1), psw1); fail_exception_expected(); }catch (DuplicateUserDataException e) { //ok } try { users.createUser(new User("new-"+login1, mail1), psw1); fail_exception_expected(); }catch (DuplicateUserDataException e) { //ok } } private void test_user_get() throws Exception { User user1 = users.getUserByLogin(login1); assertEquals(NEW, user1.getStatus()); assertEquals(login1, user1.login); assertEquals(mail1, user1.email); User user2 = users.getUserByLogin(login1); assertEquals(NEW, user2.getStatus()); assertEquals(login1, user2.login); assertEquals(mail1, user2.email); } private void test_user_create() throws Exception { int firstId = 104; mailSender.tasks.clear(); userId1 = users.createUser(new User(login1, mail1), psw1); userId2 = users.createUser(new User(login2, mail2), psw2); userId3 = users.createUser(new User(login3, mail3), psw3); userId4 = users.createUser(new User(login4, mail4), psw4); assertEquals(firstId, userId1); assertEquals(firstId+1, userId2); //mail sended assertEquals(4, mailSender.tasks.size()); } private void createUserWithInvalidData(String login, String mail, String psw, UserService users) throws Exception { try { users.createUser(new User(login, mail), psw); fail_exception_expected(); }catch (ValidationException e) { //ok } } private void resetWeb() { asyncFutures.clear(); req.clearCookies(); req.clearSessionAttrs(); resp.clearCookies(); } private void assertEmptyRemCookie() { boolean foundEmptyRemCookie = false; for(Cookie cookie : resp.cookies){ if(cookie.getName().equals(REM_TOKEN)){ assertEquals("", cookie.getValue()); assertEquals(0, cookie.getMaxAge()); foundEmptyRemCookie = true; break; } } assertTrue(String.valueOf(resp.cookies), foundEmptyRemCookie); } private void checkNotActiveUser(UserService users, String login, String email, String psw) throws Exception { try { users.checkEmailOrLoginAndPsw(email, psw); fail_exception_expected(); }catch (NotActivatedUserException e) { //ok } try { users.checkEmailOrLoginAndPsw(login, psw); fail_exception_expected(); }catch (NotActivatedUserException e) { //ok } } private void test_db_getServers() throws Exception { long serverId = -1; //init { List<ServerRow> servers = universal.select(new GetAllServers()); assertEquals(2, servers.size()); assertFalse(servers.get(0).isFull); assertFalse(servers.get(1).isFull); serverId = servers.get(1).id; } //update { universal.updateOne(new UpdateServerById(serverId, new IsFull(true))); List<ServerRow> servers = universal.select(new GetAllServers()); assertFalse(servers.get(0).isFull); assertTrue(servers.get(1).isFull); } //revert to init { universal.updateOne(new UpdateServerById(serverId, new IsFull(false))); List<ServerRow> servers = universal.select(new GetAllServers()); assertFalse(servers.get(0).isFull); assertFalse(servers.get(1).isFull); } } private void test_init_db() throws Exception { //init db check { List<ServerRow> servers = universal.select(new GetAllServers()); assertEquals(2, servers.size()); assertEquals(server1HttpUrl, servers.get(0).httpUrl); assertEquals(server1HttpsUrl, servers.get(0).httpsUrl); assertEquals(server2HttpUrl, servers.get(1).httpUrl); assertEquals(server2HttpsUrl, servers.get(1).httpsUrl); List<ChatAccount> chatsList = universal.select(new GetAllChatAccounts()); assertEquals(2, chatsList.size()); assertEquals("demo", chatsList.get(0).uid); assertEquals(1, chatsList.get(0).serverId); assertNotNull(chatsList.get(0).tariffStart); assertEquals(0, chatsList.get(0).tariffChangedInDay); assertEquals("demo2", chatsList.get(1).uid); assertEquals(1, chatsList.get(1).serverId); //operators assertEquals(set(CHAT_OWNER, CHAT_OPERATOR), chats.getAccPrivilegesForUser(chatsList.get(0).id, 100L)); assertEquals(set(CHAT_OPERATOR), chats.getAccPrivilegesForUser(chatsList.get(0).id, 101L)); } //check model { ServerRow server = chats.getServerByAcc("demo"); assertNotNull(server); assertEquals(server1HttpUrl, server.httpUrl); assertEquals(server1HttpsUrl, server.httpsUrl); } } }