All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.citrusframework.sharding.ShardingConfiguration Maven / Gradle / Ivy

The newest version!
/*
 * Copyright the original author or authors.
 *
 * 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 org.citrusframework.sharding;

import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.util.SystemProvider;

import java.util.Optional;

import static java.lang.Integer.parseInt;
import static java.lang.String.valueOf;

/**
 * A configuration class for sharded test loading and execution withing the citrus framework. It uses environment
 * variables and system properties to configure the sharding behavior.
 * 

* This class is part of the Citrus framework, designed to streamline the process of sharding test cases for efficient * and scalable testing. *

*

Configuration Example:

*

To configure the sharding behavior, set the following environment variables or system properties:

*
    *
  • Total number of shards: *
      *
    • Environment Variable: CITRUS_SHARDING_TOTAL
    • *
    • System Property: citrus.sharding.total
    • *
    • Description: Specifies the total number of shards into which the test cases will be divided.
    • *
    *
  • *
  • Shard number: *
      *
    • Environment Variable: CITRUS_SHARDING_NUMBER
    • *
    • System Property: citrus.sharding.number
    • *
    • * Description: Indicates the specific shard number of the current test loader. This should be a value between * 0 and the total number of shards minus one. *
    • *
    *
  • *
  • Shard seed: *
      *
    • Environment Variable: CITRUS_SHARDING_SEED
    • *
    • System Property: citrus.sharding.seed
    • *
    • * Description: Specifies a seed value used for shuffling test cases within a shard. Providing a consistent * seed value ensures the same shuffling order across different executions. *
    • *
    *
  • *
* *

Example Usage:

*

To configure a system with 4 total shards and assign this instance to shard number 1 (second shard, since * numbering starts at 0), set the environment variables or system properties as follows:

*
    *
  • * Set CITRUS_SHARDING_TOTAL or citrus.sharding.total to 4. *
  • *
  • * Set CITRUS_SHARDING_NUMBER or citrus.sharding.number to 1. *
  • *
  • * Optionally, set a seed for shuffling test cases using CITRUS_SHARDING_SEED * or citrus.sharding.seed. The total number of shards will be used as see by default. *
  • *
* * @see Shard */ public final class ShardingConfiguration { public static final String TOTAL_SHARD_NUMBER_PROPERTY_NAME = "citrus.sharding.total"; public static final String TOTAL_SHARD_NUMBER_ENV_VAR_NAME = TOTAL_SHARD_NUMBER_PROPERTY_NAME.replace(".", "_").toUpperCase(); public static final String SHARD_NUMBER_PROPERTY_NAME = "citrus.sharding.number"; public static final String SHARD_NUMBER_ENV_VAR_NAME = SHARD_NUMBER_PROPERTY_NAME.replace(".", "_").toUpperCase(); public static final String SHARD_SEED_PROPERTY_NAME = "citrus.sharding.seed"; public static final String SHARD_SEED_ENV_VAR_NAME = SHARD_SEED_PROPERTY_NAME.replace(".", "_").toUpperCase(); private final int totalNumberOfShards; private final int shardNumber; private final String seed; /** * Default sharding configuration which initializes the sharding with system properties and environment variables. */ public ShardingConfiguration() { this(new SystemProvider()); } /** * Constructor that allows for injecting a custom {@link SystemProvider}. This is primarily intended for testing * purposes, enabling the mocking and overriding of system environment and properties. * * @param systemProvider a provider for system environment variables and properties. */ protected ShardingConfiguration(SystemProvider systemProvider) { this(getTotalNumberOfShards(systemProvider), getShardNumber(systemProvider), systemProvider); } /** * Create a new sharding configuration with explicit total number of shards and shard number. * * @param totalNumberOfShards the total number of shards to be used. * @param shardNumber the specific shard number for this loader, zero-based. */ public ShardingConfiguration(int totalNumberOfShards, int shardNumber) { this(totalNumberOfShards, shardNumber, new SystemProvider()); } /** * Constructor that sets the total number of shards, shard number, and allows for injecting a * custom {@link SystemProvider}. Primarily used for testing purposes. * * @param totalNumberOfShards the total number of shards. * @param shardNumber the shard number for this loader, zero-based. * @param systemProvider a provider for system environment variables and properties. */ protected ShardingConfiguration(int totalNumberOfShards, int shardNumber, SystemProvider systemProvider) { this.totalNumberOfShards = totalNumberOfShards; this.shardNumber = shardNumber; seed = getSeedOrDefaultValue(systemProvider, totalNumberOfShards); sanitizeConfiguration(); } private static int getTotalNumberOfShards(SystemProvider systemProvider) { return extractEnvOrProperty(systemProvider, TOTAL_SHARD_NUMBER_ENV_VAR_NAME, TOTAL_SHARD_NUMBER_PROPERTY_NAME, 1, "Failed to calculate number of total shards, received string instead of number!"); } private static int getShardNumber(SystemProvider systemProvider) { return extractEnvOrProperty(systemProvider, SHARD_NUMBER_ENV_VAR_NAME, SHARD_NUMBER_PROPERTY_NAME, 0, "Failed to calculate shard number, received string instead of number!"); } private static String getSeedOrDefaultValue(SystemProvider systemProvider, int totalNumberOfShards) { return extractEnvOrProperty(systemProvider, SHARD_SEED_ENV_VAR_NAME, SHARD_SEED_PROPERTY_NAME) .orElseGet(() -> valueOf(totalNumberOfShards)); } private static int extractEnvOrProperty(SystemProvider systemProvider, String envVarName, String fallbackPropertyName, int defaultValue, String numberParseErrorMessage) { try { return parseInt(extractEnvOrProperty(systemProvider, envVarName, fallbackPropertyName) .orElseGet(() -> valueOf(defaultValue))); } catch (NumberFormatException e) { throw new CitrusRuntimeException(numberParseErrorMessage, e); } } private static Optional extractEnvOrProperty(SystemProvider systemProvider, String envVarName, String fallbackPropertyName) { return systemProvider.getEnv(envVarName) .or(() -> systemProvider.getProperty(fallbackPropertyName)); } private void sanitizeConfiguration() { if (totalNumberOfShards <= 0) { throw new CitrusRuntimeException("Number of total shards must be configured!"); } else if (shardNumber < 0) { throw new CitrusRuntimeException("Shard number cannot be negative!"); } else if (shardNumber >= totalNumberOfShards) { throw new CitrusRuntimeException("Shard number must be less than the total number of shards!"); } } public int getTotalNumberOfShards() { return totalNumberOfShards; } public int getShardNumber() { return shardNumber; } public int getSeed() { return seed.hashCode(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy