@@ -349,6 +349,30 @@ For commercial use, please contact jonathan@kyuss.org | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<!-- JUnit options --> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-surefire-plugin</artifactId> | |||
<version>3.0.0-M4</version> | |||
<configuration> | |||
<forkCount>1</forkCount> | |||
<reuseForks>false</reuseForks> | |||
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine> | |||
<includes> | |||
<include>bubble.test.DbInit</include> | |||
<include>bubble.test.AuthTest</include> | |||
<include>bubble.test.PaymentTest</include> | |||
<include>bubble.test.RecurringBillingTest</include> | |||
<include>bubble.test.DriverTest</include> | |||
<include>bubble.test.ProxyTest</include> | |||
<include>bubble.test.TrafficAnalyticsTest</include> | |||
<include>bubble.test.BackupTest</include> | |||
<include>bubble.test.NetworkTest</include> | |||
</includes> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
@@ -35,7 +35,8 @@ public class StripePaymentDriver extends PaymentDriverBase<StripePaymentDriverCo | |||
@Override public PaymentMethodType getPaymentMethodType() { return PaymentMethodType.credit; } | |||
private static final String PARAM_SECRET_API_KEY = "secretApiKey"; | |||
protected static final String PARAM_SECRET_API_KEY = "secretApiKey"; | |||
private static final String SIMPLE_NAME = StripePaymentDriver.class.getSimpleName();; | |||
public static final long AUTH_CACHE_DURATION = DAYS.toSeconds(7); | |||
public static final long CHARGE_CACHE_DURATION = HOURS.toSeconds(24); | |||
@@ -44,20 +45,23 @@ public class StripePaymentDriver extends PaymentDriverBase<StripePaymentDriverCo | |||
@Autowired private AccountPolicyDAO policyDAO; | |||
@Autowired private RedisService redisService; | |||
@Getter(lazy=true) private final RedisService authCache = redisService.prefixNamespace(getClass().getSimpleName()+"_auth"); | |||
@Getter(lazy=true) private final RedisService chargeCache = redisService.prefixNamespace(getClass().getSimpleName()+"_charge"); | |||
@Getter(lazy=true) private final RedisService refundCache = redisService.prefixNamespace(getClass().getSimpleName()+"_refund"); | |||
@Getter(lazy=true) private final RedisService authCache = redisService.prefixNamespace(SIMPLE_NAME +"_auth"); | |||
@Getter(lazy=true) private final RedisService chargeCache = redisService.prefixNamespace(SIMPLE_NAME +"_charge"); | |||
@Getter(lazy=true) private final RedisService refundCache = redisService.prefixNamespace(SIMPLE_NAME +"_refund"); | |||
private static final AtomicReference<String> setupDone = new AtomicReference<>(null); | |||
@Override public void postSetup() { | |||
final String apiKey = getCredentials().getParam(PARAM_SECRET_API_KEY); | |||
if (empty(apiKey)) die("postSetup: "+PARAM_SECRET_API_KEY+" not found in credentials"); | |||
if (setupDone.get() == null) { | |||
synchronized (setupDone) { | |||
if (setupDone.get() == null) { | |||
final String apiKey = getCredentials().getParam(PARAM_SECRET_API_KEY); | |||
if (empty(apiKey)) die("postSetup: "+PARAM_SECRET_API_KEY+" not found in credentials"); | |||
if (setupDone.get() != null && !setupDone.get().equals(apiKey)) { | |||
die("postSetup: cannot re-initialize with another API key (only one "+ SIMPLE_NAME +" is supported)"); | |||
} | |||
Stripe.apiKey = apiKey; | |||
setupDone.set(cloud.getUuid()); | |||
setupDone.set(apiKey); | |||
} else { | |||
log.info("postSetup: already set up"); | |||
} | |||
@@ -65,8 +69,8 @@ public class StripePaymentDriver extends PaymentDriverBase<StripePaymentDriverCo | |||
} else { | |||
log.info("postSetup: already set up"); | |||
} | |||
if (!setupDone.get().equals(cloud.getUuid())) { | |||
die("postSetup: cannot re-initialize with another API key (only one "+getClass().getSimpleName()+" is supported)"); | |||
if (!setupDone.get().equals(apiKey)) { | |||
die("postSetup: cannot re-initialize with another API key (only one "+ SIMPLE_NAME +" is supported)"); | |||
} | |||
} | |||
@@ -266,7 +266,7 @@ public class AccountDAO extends AbstractCRUDDAO<Account> implements SqlViewSearc | |||
private static final AtomicBoolean activated = new AtomicBoolean(false); | |||
@Transactional(Transactional.TxType.REQUIRES_NEW) | |||
public boolean activated() { | |||
if (activated.get()) return true; | |||
if (activated.get() && !configuration.testMode()) return true; | |||
final boolean accountsExist = countAll() > 0; | |||
if (accountsExist) activated.set(true); | |||
return accountsExist; | |||
@@ -13,6 +13,7 @@ import bubble.model.cloud.CloudService; | |||
import bubble.notify.payment.PaymentValidationResult; | |||
import bubble.server.BubbleConfiguration; | |||
import bubble.service.bill.RefundService; | |||
import bubble.service.cloud.NetworkService; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Repository; | |||
@@ -35,6 +36,7 @@ public class AccountPlanDAO extends AccountOwnedEntityDAO<AccountPlan> { | |||
@Autowired private BillDAO billDAO; | |||
@Autowired private CloudServiceDAO cloudDAO; | |||
@Autowired private BubbleNetworkDAO networkDAO; | |||
@Autowired private NetworkService networkService; | |||
@Autowired private RefundService refundService; | |||
@Autowired private BubbleConfiguration configuration; | |||
@@ -128,7 +130,7 @@ public class AccountPlanDAO extends AccountOwnedEntityDAO<AccountPlan> { | |||
final BubbleNetwork network = networkDAO.findByUuid(accountPlan.getNetwork()); | |||
if (network != null && network.getState() != BubbleNetworkState.stopped) { | |||
throw invalidEx("err.accountPlan.stopNetworkBeforeDeleting"); | |||
networkService.stopNetwork(network); | |||
} | |||
update(accountPlan.setDeleted(now()).setEnabled(false)); | |||
if (accountPlan.getNetwork() == null && accountPlan.getDeletedNetwork() != null) { | |||
@@ -25,6 +25,7 @@ import java.util.function.Function; | |||
import static bubble.ApiConstants.EP_FOOTPRINTS; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.bool; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.die; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.reflect.ReflectionUtil.copy; | |||
import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENCRYPTED_STRING; | |||
@@ -48,7 +49,9 @@ public class BubbleFootprint extends IdentifiableBase implements AccountTemplate | |||
public static final String DEFAULT_FOOTPRINT = "Worldwide"; | |||
public static final BubbleFootprint DEFAULT_FOOTPRINT_OBJECT = new BubbleFootprint() | |||
public static final BubbleFootprint DEFAULT_FOOTPRINT_OBJECT = new BubbleFootprint() { | |||
@Override public void setUuid(String uuid) { die("cannot set uuid on DEFAULT_FOOTPRINT_OBJECT"); } | |||
} | |||
.setName(DEFAULT_FOOTPRINT) | |||
.setDescription("No restrictions, run anywhere") | |||
.setTemplate(true); | |||
@@ -223,14 +223,15 @@ public class CloudService extends IdentifiableBaseParentEntity implements Accoun | |||
} | |||
private static final Map<String, CloudServiceDriver> driverCache = new ExpirationMap<>(); | |||
public static void flushDriverCache() { driverCache.clear(); } | |||
public static void clearDriverCache (String uuid) { driverCache.remove(uuid); } | |||
public <T extends CloudServiceDriver> T wireAndSetup (BubbleConfiguration configuration) { | |||
// note: CloudServiceDAO calls clearDriverCache when driver config is updated, | |||
// then the updated class/config/credentials will be used. | |||
if (!hasUuid()) { | |||
// this is a test before creation, just try to wire it up, but do not cache the result | |||
if (!hasUuid() || configuration.testMode()) { | |||
// this is a test before creation (or we are in test mode), just wire it up, but do not cache the result | |||
return _wireAndSetup(configuration); | |||
} | |||
return (T) driverCache.computeIfAbsent(getUuid(), k -> _wireAndSetup(configuration)); | |||
@@ -6,12 +6,14 @@ import bubble.model.cloud.BubbleNode; | |||
import bubble.model.cloud.CloudService; | |||
import bubble.model.cloud.notify.ReceivedNotification; | |||
import bubble.notify.DelegatedNotificationHandlerBase; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import static bubble.model.cloud.notify.NotificationType.payment_driver_response; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.die; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
@Slf4j | |||
public class NotificationHandler_payment_driver_validate extends DelegatedNotificationHandlerBase { | |||
@Autowired protected BubbleNodeDAO nodeDAO; | |||
@@ -7,11 +7,13 @@ import bubble.model.cloud.CloudService; | |||
import bubble.model.cloud.notify.ReceivedNotification; | |||
import bubble.notify.DelegatedNotificationHandlerBase; | |||
import bubble.service.cloud.StorageStreamService; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.die; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
@Slf4j | |||
public abstract class NotificationHandler_storage_driver extends DelegatedNotificationHandlerBase { | |||
@Autowired protected BubbleNodeDAO nodeDAO; | |||
@@ -22,8 +24,9 @@ public abstract class NotificationHandler_storage_driver extends DelegatedNotifi | |||
final BubbleNode sender = nodeDAO.findByUuid(n.getFromNode()); | |||
if (sender == null) die("handleNotification: sender not found: "+n.getFromNode()); | |||
final BubbleNode thisNode = configuration.getThisNode(); | |||
final StorageDriverNotification notification = json(n.getPayloadJson(), StorageDriverNotification.class); | |||
final CloudService storage = cloudDAO.findByAccountAndId(configuration.getThisNode().getAccount(), notification.getStorageService()); | |||
final CloudService storage = cloudDAO.findByAccountAndId(thisNode.getAccount(), notification.getStorageService()); | |||
if (storage == null) die("handleNotification: storage not found: "+notification.getStorageService()); | |||
handleNotification(n, sender, notification, storage); | |||
} | |||
@@ -189,7 +189,7 @@ public class AccountsResource { | |||
log.info("setContact: contact is new, sending verify message"); | |||
messageDAO.sendVerifyRequest(getRemoteHost(req), c.account, contact); | |||
} | |||
return ok(added.mask()); | |||
return ok(existing != null ? added.mask() : added); | |||
} | |||
@POST @Path("/{id}"+EP_POLICY+EP_CONTACTS+"/verify") | |||
@@ -161,7 +161,7 @@ public class ActivationService { | |||
BubbleFootprint footprint = footprintDAO.findByAccountAndId(account.getUuid(), DEFAULT_FOOTPRINT); | |||
if (footprint == null) { | |||
footprint = footprintDAO.create(DEFAULT_FOOTPRINT_OBJECT.setAccount(account.getUuid())); | |||
footprint = footprintDAO.create(new BubbleFootprint(DEFAULT_FOOTPRINT_OBJECT).setAccount(account.getUuid())); | |||
} | |||
final BubbleNetwork network = createRootNetwork(new BubbleNetwork() | |||
@@ -1,5 +1,6 @@ | |||
package bubble.service.notify; | |||
import bubble.dao.cloud.BubbleNodeDAO; | |||
import bubble.dao.cloud.notify.ReceivedNotificationDAO; | |||
import bubble.model.cloud.notify.NotificationProcessingStatus; | |||
import bubble.model.cloud.notify.ReceivedNotification; | |||
@@ -49,6 +50,10 @@ public class NotificationInboxProcessor implements Runnable { | |||
return; | |||
} | |||
} | |||
if (configuration.getBean(BubbleNodeDAO.class).findByUuid(n.getFromNode()) == null) { | |||
log.warn("processNotification: fromNode does not exist: "+n.getFromNode()); | |||
return; | |||
} | |||
handler.handleNotification(n); | |||
} | |||
@@ -341,7 +341,6 @@ err.accountPlan.callerCountryDisallowed=Your country is not currently supported | |||
err.accountPlan.disabled=Account plan is not enabled | |||
err.accountPlan.notFound=Account plan not found | |||
err.accountPlan.noVerifiedContacts=Cannot proceed, no account contact information has yet been verified | |||
err.accountPlan.stopNetworkBeforeDeleting=You must stop the bubble first, the delete the plan | |||
err.admin.cannotRemoveAdminStatusFromSelf=You cannot remove admin status from your own account | |||
err.allowedCountriesJson.length=Allowed countries list is too long | |||
err.approval.invalid=Approval cannot proceed | |||
@@ -1,6 +1,6 @@ | |||
[{ | |||
"name": "bubble", | |||
"chargeName": "BubbleStd", | |||
"chargeName": "BubbleVPN", | |||
"computeSizeType": "small", | |||
"nodesIncluded": 1, | |||
"additionalPerNodePrice": 0, | |||
@@ -11,7 +11,7 @@ | |||
"additionalBandwidthPerGbPrice": 0 | |||
}, { | |||
"name": "bubble_plus", | |||
"chargeName": "BubblePlus", | |||
"chargeName": "BubbleVPN-Plus", | |||
"computeSizeType": "medium", | |||
"nodesIncluded": 1, | |||
"additionalPerNodePrice": 0, | |||
@@ -5,6 +5,7 @@ import bubble.model.bill.AccountPaymentMethod; | |||
import bubble.model.bill.AccountPlan; | |||
import bubble.model.bill.Bill; | |||
import bubble.model.bill.BubblePlan; | |||
import com.stripe.Stripe; | |||
import java.util.concurrent.atomic.AtomicReference; | |||
@@ -15,6 +16,10 @@ public class MockStripePaymentDriver extends StripePaymentDriver { | |||
public static final AtomicReference<String> error = new AtomicReference<>(null); | |||
public static void setError(String err) { error.set(err); } | |||
@Override public void postSetup() { | |||
Stripe.apiKey = getCredentials().getParam(PARAM_SECRET_API_KEY);; | |||
} | |||
@Override public boolean authorize(BubblePlan plan, String accountPlanUuid, AccountPaymentMethod paymentMethod) { | |||
final String err = error.get(); | |||
if (err != null && (err.equals("authorize") || err.equals("all"))) { | |||
@@ -31,10 +31,8 @@ import java.util.stream.Collectors; | |||
import static bubble.ApiConstants.*; | |||
import static bubble.model.account.Account.ROOT_USERNAME; | |||
import static bubble.service.boot.StandardSelfNodeService.THIS_NODE_FILE; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.handlebars.HandlebarsUtil.applyReflectively; | |||
import static org.cobbzilla.util.io.FileUtil.abs; | |||
import static org.cobbzilla.util.io.StreamUtil.stream2string; | |||
import static org.cobbzilla.util.json.JsonUtil.FULL_MAPPER_ALLOW_COMMENTS; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
@@ -50,22 +48,10 @@ public abstract class ActivatedBubbleModelTestBase extends BubbleModelTestBase { | |||
protected Account admin; | |||
private boolean hasExistingDb = false; | |||
@Override public boolean doTruncateDb() { return false; } | |||
@Override public void beforeStart(RestServer<BubbleConfiguration> server) { | |||
// if server hbm2ddl mode is validate, do not delete node file | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
if (configuration.dbExists()) { | |||
hasExistingDb = true; | |||
log.info("beforeStart: not deleting "+abs(THIS_NODE_FILE)+" because DB exists"); | |||
} else { | |||
// start fresh | |||
if (THIS_NODE_FILE.exists() && !THIS_NODE_FILE.delete()) { | |||
die("beforeStart: error deleting " + abs(THIS_NODE_FILE)); | |||
} | |||
} | |||
// set default domain | |||
final Map<String, String> env = configuration.getEnvironment(); | |||
@@ -94,7 +80,7 @@ public abstract class ActivatedBubbleModelTestBase extends BubbleModelTestBase { | |||
server.getConfiguration().getEntityClassesReverse(); | |||
// Activate the system | |||
resetBubbleServer(); | |||
try { | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
final Map<String, Object> ctx = configuration.getEnvCtx(); | |||
@@ -14,7 +14,6 @@ import bubble.service.bill.BillingService; | |||
import com.github.jknack.handlebars.Handlebars; | |||
import com.stripe.model.Token; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.cobbzilla.util.string.StringUtil; | |||
import org.cobbzilla.wizard.client.script.SimpleApiRunnerListener; | |||
import java.util.HashMap; | |||
@@ -23,6 +22,7 @@ import java.util.Map; | |||
import static java.util.concurrent.TimeUnit.SECONDS; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.string.StringUtil.splitAndTrim; | |||
import static org.cobbzilla.util.system.Sleep.sleep; | |||
import static org.cobbzilla.util.time.TimeUtil.parseDuration; | |||
@@ -35,7 +35,7 @@ public class BubbleApiRunnerListener extends SimpleApiRunnerListener { | |||
public static final String STRIPE_TOKENIZE_CARD = "stripe_tokenize_card"; | |||
public static final String CTX_STRIPE_TOKEN = "stripeToken"; | |||
public static final long DEFAULT_BILLING_SLEEP = SECONDS.toMillis(10); | |||
public static final long DEFAULT_BILLING_SLEEP = SECONDS.toMillis(30); | |||
private BubbleConfiguration configuration; | |||
@@ -49,7 +49,7 @@ public class BubbleApiRunnerListener extends SimpleApiRunnerListener { | |||
@Override public void beforeScript(String before, Map<String, Object> ctx) throws Exception { | |||
if (before == null) return; | |||
if (before.startsWith(FAST_FORWARD_AND_BILL)) { | |||
final List<String> parts = StringUtil.splitAndTrim(before.substring(FAST_FORWARD_AND_BILL.length()), " "); | |||
final List<String> parts = splitAndTrim(before.substring(FAST_FORWARD_AND_BILL.length()), " "); | |||
final long delta = parseDuration(parts.get(0)); | |||
final long sleepTime = parts.size() > 1 ? parseDuration(parts.get(1)) : DEFAULT_BILLING_SLEEP; | |||
incrementSystemTimeOffset(delta); | |||
@@ -1,19 +0,0 @@ | |||
package bubble.test; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
@RunWith(Suite.class) | |||
@Suite.SuiteClasses({ | |||
DbInit.class, | |||
AuthTest.class, | |||
PaymentTest.class, | |||
S3StorageTest.class, | |||
DriverTest.class, | |||
ProxyTest.class, | |||
TrafficAnalyticsTest.class, | |||
BackupTest.class, | |||
NetworkTest.class, | |||
NetworkKeysTest.class | |||
}) | |||
public class BubbleCoreSuite {} |
@@ -2,11 +2,18 @@ package bubble.test; | |||
import bubble.cloud.email.mock.MockEmailDriver; | |||
import bubble.cloud.sms.mock.MockSmsDriver; | |||
import bubble.dao.account.AccountDAO; | |||
import bubble.dao.account.AccountPolicyDAO; | |||
import bubble.model.account.Account; | |||
import bubble.model.account.AccountPolicy; | |||
import bubble.model.cloud.BubbleNode; | |||
import bubble.model.cloud.CloudService; | |||
import bubble.server.BubbleConfiguration; | |||
import bubble.server.BubbleServer; | |||
import bubble.server.listener.NodeInitializerListener; | |||
import lombok.Getter; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.cobbzilla.wizard.cache.redis.RedisService; | |||
import org.cobbzilla.wizard.client.ApiClientBase; | |||
import org.cobbzilla.wizard.client.script.ApiRunner; | |||
import org.cobbzilla.wizard.client.script.ApiRunnerListener; | |||
@@ -14,6 +21,8 @@ import org.cobbzilla.wizard.server.RestServer; | |||
import org.cobbzilla.wizard.server.RestServerLifecycleListener; | |||
import org.cobbzilla.wizard.server.config.factory.StreamConfigurationSource; | |||
import org.cobbzilla.wizardtest.resources.ApiModelTestBase; | |||
import org.junit.AfterClass; | |||
import org.junit.Before; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
@@ -21,9 +30,14 @@ import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Map; | |||
import static bubble.service.boot.StandardSelfNodeService.SELF_NODE_JSON; | |||
import static bubble.service.boot.StandardSelfNodeService.THIS_NODE_FILE; | |||
import static bubble.test.BubbleTestBase.ENV_EXPORT_FILE; | |||
import static bubble.test.HandlebarsTestHelpers.registerTestHelpers; | |||
import static java.util.Arrays.asList; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.die; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.shortError; | |||
import static org.cobbzilla.util.io.FileUtil.abs; | |||
import static org.cobbzilla.util.system.CommandShell.loadShellExportsOrDie; | |||
@Slf4j | |||
@@ -33,16 +47,59 @@ public abstract class BubbleModelTestBase extends ApiModelTestBase<BubbleConfigu | |||
new NodeInitializerListener() | |||
}); | |||
protected boolean hasExistingDb = false; | |||
protected static BubbleServer server = null; | |||
// disable model cache for all tests | |||
@Override public File permCacheDir() { return null; } | |||
@Override public void beforeStart(RestServer<BubbleConfiguration> server) { | |||
server.getConfiguration().setBackupsEnabled(backupsEnabled()); | |||
super.beforeStart(server); | |||
@Before public void resetBubbleServer() { | |||
server = (BubbleServer) getServer(); | |||
try { | |||
final BubbleNode thisNode = server.getConfiguration().getThisNode(); | |||
log.info("resetBubbleServer: set server (thisNode=" + (thisNode == null ? null : thisNode.id()) + ")"); | |||
} catch (Exception e) { | |||
log.warn("resetBubbleServer: "+shortError(e)); | |||
} | |||
final BubbleConfiguration configuration = getConfiguration(); | |||
final AccountDAO accountDAO = configuration.getBean(AccountDAO.class); | |||
final AccountPolicyDAO policyDAO = configuration.getBean(AccountPolicyDAO.class); | |||
CloudService.flushDriverCache(); | |||
configuration.getBean(RedisService.class).flush(); | |||
final Account root = accountDAO.getFirstAdmin(); | |||
if (root != null) { | |||
final AccountPolicy rootPolicy = policyDAO.findSingleByAccount(root.getUuid()); | |||
policyDAO.delete(rootPolicy.getUuid()); | |||
policyDAO.create(new AccountPolicy().setAccount(root.getUuid())); | |||
} | |||
} | |||
@AfterClass public static void resetSelfJson () { | |||
if (server != null) server.stopServer(); | |||
final File selfJson = new File(SELF_NODE_JSON); | |||
if (selfJson.exists()) { | |||
if (!selfJson.delete()) die("resetSelfJson: error deleting "+abs(SELF_NODE_JSON)); | |||
} | |||
} | |||
public boolean backupsEnabled() { return false; } | |||
@Override public void beforeStart(RestServer<BubbleConfiguration> server) { | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
configuration.setBackupsEnabled(backupsEnabled()); | |||
if (configuration.dbExists()) { | |||
hasExistingDb = true; | |||
log.info("beforeStart: not deleting "+abs(THIS_NODE_FILE)+" because DB exists"); | |||
} else { | |||
// start fresh | |||
if (THIS_NODE_FILE.exists() && !THIS_NODE_FILE.delete()) { | |||
die("beforeStart: error deleting " + abs(THIS_NODE_FILE)); | |||
} | |||
} | |||
super.beforeStart(server); | |||
} | |||
@Getter(lazy=true) private final ApiClientBase _api = new TestBubbleApiClient(getConfiguration()); | |||
@Override public ApiClientBase getApi() { return get_api(); } | |||
@@ -1,9 +0,0 @@ | |||
package bubble.test; | |||
import org.junit.Test; | |||
public class NetworkKeysTest extends NetworkTestBase { | |||
@Test public void testGetNetworkKeys() throws Exception { modelTest("network/network_keys"); } | |||
} |
@@ -8,5 +8,7 @@ public class NetworkTest extends NetworkTestBase { | |||
@Test public void testRegions () throws Exception { modelTest("network/network_regions"); } | |||
@Test public void testUpgradeRole () throws Exception { modelTest("network/upgrade_role"); } | |||
@Test public void testGetNetworkKeys() throws Exception { modelTest("network/network_keys"); } | |||
} |
@@ -1,30 +1,10 @@ | |||
package bubble.test; | |||
import bubble.server.BubbleConfiguration; | |||
import bubble.service.bill.BillingService; | |||
import bubble.service.bill.StandardRefundService; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.cobbzilla.wizard.server.RestServer; | |||
import org.junit.Test; | |||
@Slf4j | |||
public class PaymentTest extends ActivatedBubbleModelTestBase { | |||
@Override protected String getManifest() { return "manifest-test"; } | |||
@Override public void beforeStart(RestServer<BubbleConfiguration> server) { | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
configuration.setSpringContextPath("classpath:/spring-mock-network.xml"); | |||
configuration.getStaticAssets().setLocalOverride(null); | |||
super.beforeStart(server); | |||
} | |||
@Override public void onStart(RestServer<BubbleConfiguration> server) { | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
configuration.getBean(StandardRefundService.class).start(); // ensure RefundService is always started | |||
configuration.getBean(BillingService.class).start(); // ensure BillingService is always started | |||
super.onStart(server); | |||
} | |||
public class PaymentTest extends PaymentTestBase { | |||
@Test public void testFreePayment () throws Exception { modelTest("payment/pay_free"); } | |||
@Test public void testCodePayment () throws Exception { modelTest("payment/pay_code"); } | |||
@@ -34,6 +14,4 @@ public class PaymentTest extends ActivatedBubbleModelTestBase { | |||
modelTest("payment/pay_credit_refund_and_restart"); | |||
} | |||
@Test public void testRecurringBilling () throws Exception { modelTest("payment/recurring_billing"); } | |||
} |
@@ -0,0 +1,26 @@ | |||
package bubble.test; | |||
import bubble.server.BubbleConfiguration; | |||
import bubble.service.bill.BillingService; | |||
import bubble.service.bill.StandardRefundService; | |||
import org.cobbzilla.wizard.server.RestServer; | |||
public class PaymentTestBase extends ActivatedBubbleModelTestBase { | |||
@Override protected String getManifest() { return "manifest-test"; } | |||
@Override public void beforeStart(RestServer<BubbleConfiguration> server) { | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
configuration.setSpringContextPath("classpath:/spring-mock-network.xml"); | |||
configuration.getStaticAssets().setLocalOverride(null); | |||
super.beforeStart(server); | |||
} | |||
@Override public void onStart(RestServer<BubbleConfiguration> server) { | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
configuration.getBean(StandardRefundService.class).start(); // ensure RefundService is always started | |||
configuration.getBean(BillingService.class).start(); // ensure BillingService is always started | |||
super.onStart(server); | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
package bubble.test; | |||
import org.junit.Test; | |||
public class RecurringBillingTest extends PaymentTestBase { | |||
@Test public void testRecurringBilling () throws Exception { modelTest("payment/recurring_billing"); } | |||
} |
@@ -8,6 +8,7 @@ import org.cobbzilla.wizard.server.RestServer; | |||
import org.junit.Test; | |||
import static java.util.concurrent.TimeUnit.DAYS; | |||
import static org.cobbzilla.util.string.StringUtil.safeParseInt; | |||
import static org.cobbzilla.util.system.Sleep.sleep; | |||
@Slf4j | |||
@@ -17,6 +18,13 @@ public class NewBlankDevServerTest extends BubbleModelTestBase { | |||
@Override protected boolean useMocks() { return false; } | |||
@Override protected boolean createSqlIndexes () { return true; } | |||
@Override public void beforeStart(RestServer<BubbleConfiguration> server) { | |||
final BubbleConfiguration configuration = server.getConfiguration(); | |||
final Integer port = safeParseInt(configuration.getEnvironment().get("BUBBLE_SERVER_PORT")); | |||
configuration.getHttp().setPort(port); | |||
super.beforeStart(server); | |||
} | |||
@Override public void onStart(RestServer<BubbleConfiguration> server) { | |||
getConfiguration().getBean(EntityConfigsResource.class).getAllowPublic().set(true); | |||
super.onStart(server); | |||
@@ -1,5 +1,6 @@ | |||
package bubble.test; | |||
package bubble.test.live; | |||
import bubble.test.NetworkTestBase; | |||
import org.junit.Test; | |||
public class GoDaddyDnsTest extends NetworkTestBase { |
@@ -1,9 +1,10 @@ | |||
package bubble.test; | |||
package bubble.test.live; | |||
import bubble.cloud.CloudServiceDriver; | |||
import bubble.cloud.dns.route53.Route53DnsDriver; | |||
import bubble.model.cloud.BubbleDomain; | |||
import bubble.model.cloud.CloudService; | |||
import bubble.test.NetworkTestBase; | |||
import org.junit.Test; | |||
import java.util.Arrays; |
@@ -1,4 +1,4 @@ | |||
package bubble.test; | |||
package bubble.test.live; | |||
import bubble.cloud.CloudServiceType; | |||
import bubble.cloud.storage.s3.S3StorageConfig; | |||
@@ -7,6 +7,7 @@ import bubble.model.cloud.CloudService; | |||
import bubble.model.cloud.RekeyRequest; | |||
import bubble.model.cloud.StorageMetadata; | |||
import bubble.notify.storage.StorageListing; | |||
import bubble.test.NetworkTestBase; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang3.RandomUtils; | |||
import org.apache.http.HttpHeaders; |
@@ -107,7 +107,6 @@ | |||
"response": { | |||
"check": [ | |||
{"condition": "json.getType().name() == 'email'"}, | |||
{"condition": "json.getInfo() == 'user-multifactor_auth@example.com'"}, | |||
{"condition": "json.getAuthFactor().name() == 'required'"} | |||
] | |||
} | |||
@@ -540,8 +539,7 @@ | |||
}, | |||
"response": { | |||
"check": [ | |||
{"condition": "json.getAuthFactor().name() == 'sufficient'"}, | |||
{"condition": "json.getInfo() == 'foo@example.com'"} | |||
{"condition": "json.getAuthFactor().name() == 'sufficient'"} | |||
] | |||
} | |||
}, | |||
@@ -711,8 +709,8 @@ | |||
"check": [ | |||
{"condition": "json.getAccountContacts() != null"}, | |||
{"condition": "json.getAccountContacts().length == 2"}, | |||
{"condition": "!json.getAccountContacts()[0].getInfo() != 'bar@example.com'"}, | |||
{"condition": "!json.getAccountContacts()[1].getInfo() != 'bar@example.com'"} | |||
{"condition": "!json.getAccountContacts()[0].getInfo().startsWith('bar')"}, | |||
{"condition": "!json.getAccountContacts()[1].getInfo().startsWith('bar')"} | |||
] | |||
} | |||
} |
@@ -177,26 +177,6 @@ | |||
} | |||
}, | |||
{ | |||
"comment": "try to delete plan, must stop network first", | |||
"request": { | |||
"method": "delete", | |||
"uri": "me/plans/{{accountPlan.uuid}}" | |||
}, | |||
"response": { | |||
"status": 422, | |||
"check": [{"condition": "json.has('err.accountPlan.stopNetworkBeforeDeleting')"}] | |||
} | |||
}, | |||
{ | |||
"comment": "delete network", | |||
"request": { | |||
"method": "delete", | |||
"uri": "me/networks/{{accountPlan.network}}" | |||
} | |||
}, | |||
{ | |||
"comment": "delete plan", | |||
"request": { | |||
@@ -41,7 +41,7 @@ staticAssets: | |||
STRIPE_PUBLIC_API_KEY: {{STRIPE_PUBLIC_API_KEY}} | |||
http: | |||
port: {{#exists BUBBLE_SERVER_PORT}}{{BUBBLE_SERVER_PORT}}{{else}}8090{{/exists}} | |||
port: 0 | |||
baseUri: /api | |||
jersey: | |||
@@ -1 +1 @@ | |||
Subproject commit 8f3c566b05bdced05af7f69d4cdf63f672f8fc61 | |||
Subproject commit f4062af3bc423f88705fc90bebc4fbab15096e83 |