From 026ed4126bec169ef7d255cbce4823297acd5a59 Mon Sep 17 00:00:00 2001 From: Jakub Stejskal Date: Wed, 3 Jul 2024 18:39:56 +0200 Subject: [PATCH 1/2] Use DataFaker instead of our implementation Signed-off-by: Jakub Stejskal --- pom.xml | 8 + .../skodjob/loadgenerator/DataGenerator.java | 49 +---- .../java/io/skodjob/loadgenerator/Utils.java | 64 ------ .../loadgenerator/enums/ETemplateType.java | 18 +- .../loadgenerator/handlers/IotDevice.java | 193 +++++------------- .../loadgenerator/handlers/Payroll.java | 45 ++++ .../loadgenerator/handlers/People.java | 184 ----------------- src/main/resources/data/companies.txt | 20 -- src/main/resources/data/iot_vendors.txt | 10 - src/main/resources/data/mail_provider.txt | 6 - src/main/resources/data/nameF.txt | 50 ----- src/main/resources/data/nameM.txt | 50 ----- src/main/resources/data/surnames.txt | 100 --------- src/main/resources/templates/iot_device.json | 9 - .../resources/templates/payroll_employee.json | 11 - .../loadgenerator/DataGeneratorTest.java | 6 +- 16 files changed, 120 insertions(+), 703 deletions(-) delete mode 100644 src/main/java/io/skodjob/loadgenerator/Utils.java create mode 100644 src/main/java/io/skodjob/loadgenerator/handlers/Payroll.java delete mode 100644 src/main/java/io/skodjob/loadgenerator/handlers/People.java delete mode 100644 src/main/resources/data/companies.txt delete mode 100644 src/main/resources/data/iot_vendors.txt delete mode 100644 src/main/resources/data/mail_provider.txt delete mode 100644 src/main/resources/data/nameF.txt delete mode 100644 src/main/resources/data/nameM.txt delete mode 100644 src/main/resources/data/surnames.txt delete mode 100644 src/main/resources/templates/iot_device.json delete mode 100644 src/main/resources/templates/payroll_employee.json diff --git a/pom.xml b/pom.xml index 096c7d7..b77d4bc 100644 --- a/pom.xml +++ b/pom.xml @@ -84,6 +84,7 @@ 5.10.2 1.10.2 3.3.0 + 2.3.0 2.17.1 @@ -164,6 +165,13 @@ ${spotbugs.version} provided + + + + net.datafaker + datafaker + ${datafaker.version} + diff --git a/src/main/java/io/skodjob/loadgenerator/DataGenerator.java b/src/main/java/io/skodjob/loadgenerator/DataGenerator.java index 6b993e8..384db7c 100644 --- a/src/main/java/io/skodjob/loadgenerator/DataGenerator.java +++ b/src/main/java/io/skodjob/loadgenerator/DataGenerator.java @@ -6,16 +6,12 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.skodjob.loadgenerator.enums.ETemplateType; import io.skodjob.loadgenerator.handlers.IotDevice; -import io.skodjob.loadgenerator.handlers.People; +import io.skodjob.loadgenerator.handlers.Payroll; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.Objects; /** @@ -24,7 +20,6 @@ public class DataGenerator { private static final Logger LOGGER = LogManager.getLogger(DataGenerator.class); - private final String templateJson; private final ETemplateType templateType; /** @@ -32,35 +27,9 @@ public class DataGenerator { * * @param templateType the type of template to be used for data generation */ - // The suppression is needed due to false positive result - @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") public DataGenerator(ETemplateType templateType) { this.templateType = Objects.requireNonNull(templateType, "TemplateType cannot be null!"); - try { - this.templateJson = loadTemplate(templateType.getTemplatePath()); - } catch (IOException e) { - LOGGER.error("Error loading template", e); - throw new RuntimeException("Failed to load template: " + templateType.getTemplatePath(), e); - } - - LOGGER.info("Loaded {} template with location {}", templateType.getTemplateName(), - templateType.getTemplatePath()); - } - - /** - * Loads the template from the specified path. - * - * @param templateName the name of the template file - * @return the content of the template file as a string - * @throws IOException if an I/O error occurs while loading the template - */ - private String loadTemplate(String templateName) throws IOException { - try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(templateName)) { - if (inputStream == null) { - throw new IOException("Template not found: " + templateName); - } - return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); - } + LOGGER.info("Initialized DataGenerator with template type {}", templateType.getTemplateName()); } /** @@ -71,9 +40,9 @@ private String loadTemplate(String templateName) throws IOException { public String generateStringData() { switch (this.templateType) { case PAYROLL_EMPLOYEE: - return Utils.stripWhitespace(People.fillTemplate(this.templateJson)); + return Payroll.generateData(); case IOT_DEVICE: - return Utils.stripWhitespace(IotDevice.fillTemplate(this.templateJson)); + return IotDevice.generateData(); default: throw new IllegalArgumentException("Unknown template type: " + this.templateType); } @@ -83,10 +52,12 @@ public String generateStringData() { * Generates JSON data based on the template type. * * @return the generated JSON data - * @throws IOException if an I/O error occurs while generating JSON data */ - public JsonNode generateJsonData() throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readTree(generateStringData()); + public JsonNode generateJsonData() { + try { + return new ObjectMapper().readTree(generateStringData()); + } catch (Exception e) { + throw new RuntimeException("Error generating JSON data", e); + } } } diff --git a/src/main/java/io/skodjob/loadgenerator/Utils.java b/src/main/java/io/skodjob/loadgenerator/Utils.java deleted file mode 100644 index e18d7aa..0000000 --- a/src/main/java/io/skodjob/loadgenerator/Utils.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Skodjob authors. - * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). - */ -package io.skodjob.loadgenerator; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Utility class providing common methods for data loading and JSON manipulation. - */ -public class Utils { - - private Utils() {} - - /** - * Loads data from a file and returns it as a list of strings. - * - * @param filename the name of the file to load - * @return a list of strings containing the data from the file - * @throws IOException if an I/O error occurs - */ - public static List loadData(String filename) throws IOException { - try (InputStream inputStream = Utils.class.getResourceAsStream(filename); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { - return reader.lines().collect(Collectors.toList()); - } - } - - /** - * Removes all whitespace characters from a JSON string. - * - * @param jsonString the original JSON string - * @return the JSON string without whitespace characters - */ - public static String stripWhitespace(String jsonString) { - return jsonString.replaceAll("\\s+", ""); - } - - /** - * Converts a JSON string into a pretty-printed JSON format. - * - * @param jsonString the original JSON string - * @return the pretty-printed JSON string - * @throws IOException if an I/O error occurs - */ - public static String prettyPrintJson(String jsonString) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.enable(SerializationFeature.INDENT_OUTPUT); - - JsonNode jsonNode = objectMapper.readTree(jsonString); - return objectMapper.writeValueAsString(jsonNode); - } -} diff --git a/src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java b/src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java index 86df708..6cda6ab 100644 --- a/src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java +++ b/src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java @@ -11,25 +11,22 @@ public enum ETemplateType { /** * Template for People Payrol data */ - PAYROLL_EMPLOYEE("payroll_employee", "templates/payroll_employee.json"), + PAYROLL_EMPLOYEE("payroll_employee"), /** * Template for IoT device data */ - IOT_DEVICE("iot_device", "templates/iot_device.json"); + IOT_DEVICE("iot_device"); private final String templateName; - private final String templatePath; /** * Constructor for ETemplateType. * * @param templateName the name of the template - * @param templatePath the path to the template file */ - ETemplateType(String templateName, String templatePath) { + ETemplateType(String templateName) { this.templateName = templateName; - this.templatePath = templatePath; } /** @@ -40,13 +37,4 @@ public enum ETemplateType { public String getTemplateName() { return templateName; } - - /** - * Gets the path to the template file. - * - * @return the path to the template file - */ - public String getTemplatePath() { - return templatePath; - } } diff --git a/src/main/java/io/skodjob/loadgenerator/handlers/IotDevice.java b/src/main/java/io/skodjob/loadgenerator/handlers/IotDevice.java index 92363b6..3bac317 100644 --- a/src/main/java/io/skodjob/loadgenerator/handlers/IotDevice.java +++ b/src/main/java/io/skodjob/loadgenerator/handlers/IotDevice.java @@ -4,34 +4,15 @@ */ package io.skodjob.loadgenerator.handlers; -import io.skodjob.loadgenerator.Utils; +import net.datafaker.Faker; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Random; +import java.util.Locale; /** - * This class generates random IoT device data for use in templates. + * This class is responsible for generating IoT device data using the Faker library. */ public class IotDevice { - private static final Random RANDOM = new Random(); - - private static final String STATE_ACTIVE = "active"; - private static final String STATE_INACTIVE = "inactive"; - private static final String STATE_ERROR = "error"; - private static final String STATE_ON = "on"; - private static final String STATE_OFF = "off"; - private static final List ACTIVITY_STATES = Arrays.asList(STATE_ACTIVE, STATE_INACTIVE, STATE_ERROR); - private static final List POWER_STATES = Arrays.asList(STATE_ON, STATE_OFF); - - private static final String BEHAVIOR_ON = STATE_ON; - private static final String BEHAVIOR_OFF = STATE_OFF; - private static final String BEHAVIOR_TOGGLE = "toggle"; - private static final String BEHAVIOR_PREVIOUS = "previous"; - private static final List BEHAVIORS = Arrays.asList( - BEHAVIOR_ON, BEHAVIOR_OFF, BEHAVIOR_TOGGLE, BEHAVIOR_PREVIOUS); - private static final List VENDORS; + private static final Faker FAKER = new Faker(); private static final String TYPE_LIGHT = "light"; private static final String TYPE_BUTTON = "button"; @@ -40,128 +21,67 @@ public class IotDevice { private static final String TYPE_CUSTOM = "custom"; private static final String TYPE_GATE = "gate"; - private static final List TYPES = Arrays.asList(TYPE_LIGHT, TYPE_BUTTON, TYPE_THERMOMETER, - TYPE_PLUG, TYPE_CUSTOM, TYPE_GATE); - - static { - try { - VENDORS = Utils.loadData("/data/iot_vendors.txt"); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Default constructor - */ - private IotDevice() { - - } - - /** - * Generates a random IoT device type. - * - * @return A random IoT device type. - */ - private static String generateType() { - return TYPES.get(RANDOM.nextInt(TYPES.size())); - } - /** - * Generates a random IPv4 address. + * Generates a random power state (on/off). * - * @return A random IPv4 address. - */ - private static String generateIPv4() { - return RANDOM.nextInt(256) + "." + RANDOM.nextInt(256) + "." + RANDOM.nextInt(256) + "." + RANDOM.nextInt(256); - } - - /** - * Generates a random activity state. - * - * @return A random activity state. - */ - private static String generateActivityState() { - return ACTIVITY_STATES.get(RANDOM.nextInt(ACTIVITY_STATES.size())); - } - - /** - * Generates a random power state. - * - * @return A random power state. + * @return a randomly generated power state */ private static String generatePowerState() { - return POWER_STATES.get(RANDOM.nextInt(POWER_STATES.size())); + return FAKER.options().option("on", "off"); } /** - * Generates a random MAC address. + * Generates a random power on behavior (on/off/toggle/previous). * - * @return A random MAC address. + * @return a randomly generated power on behavior */ - private static String generateMacAddress() { - byte[] macAddr = new byte[6]; - RANDOM.nextBytes(macAddr); - - macAddr[0] = (byte) (macAddr[0] & (byte) 254); - - StringBuilder mac = new StringBuilder(18); - for (byte b : macAddr) { - if (mac.length() > 0) mac.append(":"); - mac.append(String.format("%02x", b)); - } - return mac.toString(); - } - - /** - * Generates a random ID. - * - * @return A random ID. - */ - private static String generateId() { - return String.valueOf(RANDOM.nextInt(1000000)); + private static String generatePowerOnBehavior() { + return FAKER.options().option("on", "off", "toggle", "previous"); } /** - * Generates the current timestamp. + * Generates a random vendor name. * - * @return The current timestamp. + * @return a randomly generated vendor name */ - private static String generateLastUpdate() { - return String.valueOf(System.currentTimeMillis()); + private static String generateVendor() { + return FAKER.options().option("ikea", "apple", "tasmota", "sencor", "amazon", "google", "xiaomi"); } /** - * Generates a random link quality (0-100). + * Generates a random activity state (active/inactive/error). * - * @return A random link quality. + * @return a randomly generated activity state */ - private static String generateLinkQuality() { - return String.format("%s", RANDOM.nextInt(101)); + private static String generateActivityState() { + return FAKER.options().option("active", "inactive", "error"); } /** - * Generates data for a specific IoT device type. + * Generates a JSON data section for the specified device type. * - * @param type The type of the IoT device. - * @return The generated data for the IoT device. + * @param type the type of the device + * @return a JSON string representing the data section for the specified device type */ - private static String generateData(String type) { + private static String generateDataSection(String type) { switch (type) { case TYPE_LIGHT: return String.format("{\"power\": \"%s\", \"brightness\": %d, \"power_on_behavior\": \"%s\"}", - generatePowerState(), RANDOM.nextInt(255), generatePowerOnBehavior()); + generatePowerState(), FAKER.number().numberBetween(0, 254), generatePowerOnBehavior()); case TYPE_PLUG: return String.format("{\"power\": \"%s\", \"energy_current\": {\"state\": %.3f, \"unit\": \"A\"}, " + "\"energy_today\": {\"state\": %.3f, \"unit\": \"kWh\"}}", - generatePowerState(), RANDOM.nextDouble(), RANDOM.nextDouble() * 10); + generatePowerState(), FAKER.number().randomDouble(3, 0, 1), + FAKER.number().randomDouble(3, 0, 10)); case TYPE_BUTTON: return String.format("{\"power\": \"%s\", \"battery\": {\"value\": %d, \"unit\": \"%%\"}}", - generatePowerState(), RANDOM.nextInt(101)); + generatePowerState(), FAKER.number().numberBetween(0, 100)); case TYPE_THERMOMETER: return String.format("{\"temperature\": %.2f, \"humidity\": %.2f, " + "\"battery\": {\"value\": %d, \"unit\": \"%%\"}}", - RANDOM.nextDouble() * 70 - 30, RANDOM.nextDouble() * 80 + 10, RANDOM.nextInt(101)); + FAKER.number().randomDouble(2, -30, 40), + FAKER.number().randomDouble(2, 10, 90), + FAKER.number().numberBetween(0, 100)); case TYPE_GATE: return String.format("{\"vendor\": \"%s\", \"state\": \"%s\"}", generateVendor(), generateActivityState()); @@ -171,39 +91,28 @@ private static String generateData(String type) { } /** - * Generates a random power-on behavior. + * Generates IoT device data using the Faker library. * - * @return A random power-on behavior. + * @return the generated IoT device data as a JSON string */ - private static String generatePowerOnBehavior() { - return BEHAVIORS.get(RANDOM.nextInt(BEHAVIORS.size())); - } - - /** - * Generates a random vendor. - * - * @return A random vendor. - */ - private static String generateVendor() { - return VENDORS.get(RANDOM.nextInt(VENDORS.size())); - } - - /** - * Fills the template with random IoT device data. - * - * @param template The template to be filled. - * @return The filled template. - */ - public static String fillTemplate(String template) { - String type = generateType(); - template = template.replace("@ipv4", "\"%s\"".formatted(generateIPv4())); - template = template.replace("@mac", "\"%s\"".formatted(generateMacAddress())); - template = template.replace("@id", "\"%s\"".formatted(generateId())); - template = template.replace("@type", "\"" + type + "\""); - template = template.replace("@last_update", "\"%s\"".formatted(generateLastUpdate())); - template = template.replace("@link_quality", generateLinkQuality()); - template = template.replace("@data", generateData(type)); - - return template; + public static String generateData() { + String ipv4 = FAKER.internet().ipV4Address(); + String mac = FAKER.internet().macAddress(); + String id = String.valueOf(FAKER.number().numberBetween(10000, 999999)); + String type = FAKER.options().option(TYPE_LIGHT, TYPE_BUTTON, TYPE_THERMOMETER, + TYPE_PLUG, TYPE_CUSTOM, TYPE_GATE); + String lastUpdate = String.valueOf(System.currentTimeMillis()); + int linkQuality = FAKER.number().numberBetween(0, 100); + String data = generateDataSection(type); + + return String.format(Locale.US, + "{\"IPV4\":\"%s\"," + + "\"MAC\":\"%s\"," + + "\"ID\":\"%s\"," + + "\"TYPE\":\"%s\"," + + "\"LAST_UPDATE\":\"%s\"," + + "\"LINK_QUALITY\":%d," + + "\"DATA\":%s}", + ipv4, mac, id, type, lastUpdate, linkQuality, data); } } diff --git a/src/main/java/io/skodjob/loadgenerator/handlers/Payroll.java b/src/main/java/io/skodjob/loadgenerator/handlers/Payroll.java new file mode 100644 index 0000000..e66acf3 --- /dev/null +++ b/src/main/java/io/skodjob/loadgenerator/handlers/Payroll.java @@ -0,0 +1,45 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.loadgenerator.handlers; + +import net.datafaker.Faker; + +import java.util.Locale; + +/** + * This class generates random people-related data for use in templates. + */ +public class Payroll { + private static final Faker FAKER = new Faker(); + + /** + * Generates payroll employee data using the Faker library. + * + * @return the generated payroll employee data as a JSON string + */ + public static String generateData() { + String employeeId = String.valueOf(FAKER.number().numberBetween(10000, 999999)); + String firstName = FAKER.name().firstName(); + String lastName = FAKER.name().lastName(); + int age = FAKER.number().numberBetween(18, 60); + String ssn = FAKER.idNumber().ssnValid(); + double hourlyRate = FAKER.number().randomDouble(2, 10, 50); + String gender = FAKER.demographic().sex(); + String email = FAKER.internet().emailAddress(); + String company = FAKER.company().name(); + + return String.format(Locale.US, + "{\"employee_id\":\"%s\"," + + "\"first_name\":\"%s\"," + + "\"last_name\":\"%s\"," + + "\"age\":%d," + + "\"ssn\":\"%s\"," + + "\"hourly_rate\":%.2f," + + "\"gender\":\"%s\"," + + "\"email\":\"%s\"," + + "\"company\":\"%s\"}", + employeeId, firstName, lastName, age, ssn, hourlyRate, gender, email, company); + } +} diff --git a/src/main/java/io/skodjob/loadgenerator/handlers/People.java b/src/main/java/io/skodjob/loadgenerator/handlers/People.java deleted file mode 100644 index c1dd0cf..0000000 --- a/src/main/java/io/skodjob/loadgenerator/handlers/People.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright Skodjob authors. - * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). - */ -package io.skodjob.loadgenerator.handlers; - -import io.skodjob.loadgenerator.Utils; - -import java.io.IOException; -import java.util.List; -import java.util.Locale; -import java.util.Random; - -/** - * This class generates random people-related data for use in templates. - */ -public class People { - private static final Random RANDOM = new Random(); - - private static final List NAMES_F; - private static final List NAMES_M; - private static final List SURNAMES; - private static final List COMPANIES; - private static final List EMAIL_PROVIDERS; - - private static final String MALE = "Male"; - private static final String FEMALE = "Female"; - - static { - try { - NAMES_F = Utils.loadData("/data/nameF.txt"); - NAMES_M = Utils.loadData("/data/nameM.txt"); - SURNAMES = Utils.loadData("/data/surnames.txt"); - COMPANIES = Utils.loadData("/data/companies.txt"); - EMAIL_PROVIDERS = Utils.loadData("/data/mail_provider.txt"); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Default constructor - */ - private People() { - - } - - /** - * Generates a random male first name. - * - * @return A random male first name. - */ - public static String generateMaleFirstName() { - return NAMES_M.get(RANDOM.nextInt(NAMES_M.size())); - } - - /** - * Generates a random female first name. - * - * @return A random female first name. - */ - public static String generateFemaleFirstName() { - return NAMES_F.get(RANDOM.nextInt(NAMES_F.size())); - } - - /** - * Generates a random surname. - * - * @return A random surname. - */ - public static String generateSurname() { - return SURNAMES.get(RANDOM.nextInt(SURNAMES.size())); - } - - /** - * Generates a random company name. - * - * @return A random company name. - */ - public static String generateCompany() { - return COMPANIES.get(RANDOM.nextInt(COMPANIES.size())); - } - - /** - * Generates a random email address. - * - * @param name The first name to be included in the email address. - * @param surname The surname to be included in the email address. - * @param company The company to be included in the email address. - * @return A random email address. - */ - public static String generateEmail(String name, String surname, String company) { - return "%s.%s@%s".formatted(name, surname, company); - } - - /** - * Generates a random age between 18 and 60. - * - * @return A random age between 18 and 60. - */ - public static String generateAge() { - return String.valueOf(18 + RANDOM.nextInt(43)); // Generate age between 18 and 60 - } - - /** - * Generates a random Social Security Number (SSN). - * - * @return A random SSN. - */ - public static String generateSSN() { - return String.format("%03d-%02d-%04d", - RANDOM.nextInt(1000), - RANDOM.nextInt(100), - RANDOM.nextInt(10000)); - } - - /** - * Generates a random hourly rate between $10.00 and $50.00. - * - * @return A random hourly rate. - */ - public static String generateHourlyRate() { - // Generate hourly rate between $10.00 and $50.00 - return String.format("%.2f", 10 + (RANDOM.nextDouble() * 40)); - } - - /** - * Generates a random gender. - * - * @return A random gender. - */ - public static String generateGender() { - return RANDOM.nextBoolean() ? MALE : FEMALE; - } - - /** - * Generates a random employee ID. - * - * @return A random employee ID. - */ - public static String generateEmployeeId() { - return String.format("%s", (1000 + RANDOM.nextInt(900000))); - } - - /** - * Generates a random email provider. - * - * @return A random email provider. - */ - public static String generateEmailProvider() { - return EMAIL_PROVIDERS.get(RANDOM.nextInt(EMAIL_PROVIDERS.size())); - } - - /** - * Fills the template with random people-related data. - * - * @param template The template to be filled. - * @return The filled template. - */ - public static String fillTemplate(String template) { - String gender = generateGender(); - String name; - if (gender.equals(MALE)) { - name = generateMaleFirstName(); - } else { - name = generateFemaleFirstName(); - } - String surname = generateSurname(); - String company = generateCompany(); - - template = template.replace("@employee_id", "\"%s\"".formatted(generateEmployeeId())); - template = template.replace("@surname", "\"%s\"".formatted(surname)); - template = template.replace("@name", "\"%s\"".formatted(name)); - template = template.replace("@age", generateAge()); - template = template.replace("@ssn", "\"%s\"".formatted(generateSSN())); - template = template.replace("@hourly_rate", generateHourlyRate()); - template = template.replace("@gender", "\"%s\"".formatted(gender)); - template = template.replace("@email", "\"%s\"".formatted(generateEmail(name, surname, - generateEmailProvider()).toLowerCase(Locale.US))); - template = template.replace("@company", "\"%s\"".formatted(company)); - - return template; - } -} diff --git a/src/main/resources/data/companies.txt b/src/main/resources/data/companies.txt deleted file mode 100644 index e2b6088..0000000 --- a/src/main/resources/data/companies.txt +++ /dev/null @@ -1,20 +0,0 @@ -Google -Microsoft -Apple -Amazon -Facebook -Tesla -IBM -Intel -Samsung -Toyota -General Electric -BMW -Sony -Cisco -Oracle -Nike -Coca-Cola -PepsiCo -Unilever -Johnson & Johnson diff --git a/src/main/resources/data/iot_vendors.txt b/src/main/resources/data/iot_vendors.txt deleted file mode 100644 index 483d8b7..0000000 --- a/src/main/resources/data/iot_vendors.txt +++ /dev/null @@ -1,10 +0,0 @@ -ikea -apple -tasmota -sencor -amazon -apple -xiaomi -samsung -panasonic -parkside diff --git a/src/main/resources/data/mail_provider.txt b/src/main/resources/data/mail_provider.txt deleted file mode 100644 index 83164b7..0000000 --- a/src/main/resources/data/mail_provider.txt +++ /dev/null @@ -1,6 +0,0 @@ -email.com -seznam.cz -gmail.com -outlook.com -yahoo.com -icloud.com diff --git a/src/main/resources/data/nameF.txt b/src/main/resources/data/nameF.txt deleted file mode 100644 index b489432..0000000 --- a/src/main/resources/data/nameF.txt +++ /dev/null @@ -1,50 +0,0 @@ -Maria -Isabella -Fatima -Hannah -Sofia -Aisha -Mei -Elena -Moana -Sakura -Natalia -Irina -Amina -Greta -Aria -Marta -Lila -Marwa -Zara -Pooja -Yara -Katya -Carmen -Noriko -Alina -Misaki -Layla -Ksenia -Maya -Zainab -Noor -Aaliyah -Mia -Ewa -Chihiro -Irena -Fumiko -Ludmila -Chloe -Zoya -Eva -Siti -Priya -Suresh -Thiago -Greta -Aya -Misaki -Fumiko -Ewa diff --git a/src/main/resources/data/nameM.txt b/src/main/resources/data/nameM.txt deleted file mode 100644 index 580940b..0000000 --- a/src/main/resources/data/nameM.txt +++ /dev/null @@ -1,50 +0,0 @@ -John -Hiroshi -Ahmed -Li -Vladimir -Pedro -Sergei -Antonio -Yuki -Carlos -Ivan -Alexei -Miguel -Jing -Omar -Haruto -Rahul -Abdullah -Juan -Igor -Bao -Diego -Kofi -Kenji -Abdul -Yu -Nikola -Stefan -Niko -Dimitri -Subhash -Katya -Jorge -Mahmud -Faisal -Joseph -Marco -Leandro -Samir -Matteo -Valentin -Jean -Franz -Bashir -Musa -Saif -Rashid -Olaf -Ali -Simran diff --git a/src/main/resources/data/surnames.txt b/src/main/resources/data/surnames.txt deleted file mode 100644 index 49d02a6..0000000 --- a/src/main/resources/data/surnames.txt +++ /dev/null @@ -1,100 +0,0 @@ -Smith -Muller -Kim -Skywalker -Wang -Johnson -Santos -Lopez -Brown -Patel -Li -Gonzalez -Nguyen -Martin -Rodriguez -Perez -Lee -Silva -Ahmed -Kowalski -Schmidt -Singh -Costa -Ivanov -Taylor -Hoxha -Davis -Chen -Rossi -Kimura -Torres -Sousa -Tan -Smith -Hernandez -Bashir -Johnson -Robinson -Lopez -Brown -Patel -Wilson -Garcia -Singh -Lee -Chen -Thompson -Evans -Harris -Baker -Carter -Murphy -Walker -Martinez -Diaz -Roberts -Jones -Sanchez -Kelly -Wright -Adams -Rivera -Mitchell -Young -Price -Bell -Scott -Torres -Morris -Reed -Cook -Howard -Brooks -Morgan -Bailey -Reed -Rivera -Cooper -Richardson -Cox -Ward -Gray -James -Watson -Perry -Russell -Foster -Powell -Long -Patterson -Hughes -Flores -Washington -Butler -Simmons -Foster -Gonzales -Bryant -Alexander -Russell diff --git a/src/main/resources/templates/iot_device.json b/src/main/resources/templates/iot_device.json deleted file mode 100644 index 375deaa..0000000 --- a/src/main/resources/templates/iot_device.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "IPV4": @ipv4, - "MAC": @mac, - "ID": @id, - "TYPE": @type, - "LAST_UPDATE": @last_update, - "LINK_QUALITY": @link_quality, - "DATA": @data -} diff --git a/src/main/resources/templates/payroll_employee.json b/src/main/resources/templates/payroll_employee.json deleted file mode 100644 index dd2e852..0000000 --- a/src/main/resources/templates/payroll_employee.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "employee_id": @employee_id, - "first_name": @name, - "last_name": @surname, - "age": @age, - "ssn": @ssn, - "hourly_rate": @hourly_rate, - "gender": @gender, - "email": @email, - "company": @company -} diff --git a/src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java b/src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java index 48bcbaf..4d4fa7b 100644 --- a/src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java +++ b/src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java @@ -70,14 +70,14 @@ void testInvalidTemplateType() { public static Stream testRepeatedParameters() { String peopleRegex = "\\{" + "\"employee_id\":\"\\d+\"," - + "\"first_name\":\"[A-Za-z]+\"," - + "\"last_name\":\"[A-Za-z]+\"," + + "\"first_name\":\"[A-Za-z']+\"," + + "\"last_name\":\"[A-Za-z']+\"," + "\"age\":\\d+," + "\"ssn\":\"\\d+-\\d+-\\d+\"," + "\"hourly_rate\":\\d+\\.\\d+," + "\"gender\":\"(Male|Female)\"," + "\"email\":\"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\"," - + "\"company\":\"[A-Za-z-& ]+\"" + + "\"company\":\"[A-Za-z-&\\.\\,\\-' ]+\"" + "\\}"; String iotRegex = "\\{" From 9a42f2491ab3089dda47387c16548c3dc8bef4cd Mon Sep 17 00:00:00 2001 From: Jakub Stejskal Date: Thu, 11 Jul 2024 09:52:58 +0200 Subject: [PATCH 2/2] Extend a little bit current usage + some improvements Signed-off-by: Jakub Stejskal --- pom.xml | 18 +- .../DataGenerator.java | 31 ++- .../datagenerator/enums/ETemplateType.java | 67 ++++++ .../datagenerator/handlers/Flights.java | 77 +++++++ .../handlers/IotDevice.java | 15 +- .../datagenerator/handlers/PaymentFiat.java | 191 ++++++++++++++++++ .../handlers/Payroll.java | 15 +- .../datagenerator/handlers/StarGate.java | 54 +++++ .../datagenerator/handlers/StarWars.java | 59 ++++++ .../loadgenerator/enums/ETemplateType.java | 40 ---- .../datagenerator/DataGeneratorTest.java | 174 ++++++++++++++++ .../loadgenerator/DataGeneratorTest.java | 103 ---------- 12 files changed, 685 insertions(+), 159 deletions(-) rename src/main/java/io/skodjob/{loadgenerator => datagenerator}/DataGenerator.java (66%) create mode 100644 src/main/java/io/skodjob/datagenerator/enums/ETemplateType.java create mode 100644 src/main/java/io/skodjob/datagenerator/handlers/Flights.java rename src/main/java/io/skodjob/{loadgenerator => datagenerator}/handlers/IotDevice.java (94%) create mode 100644 src/main/java/io/skodjob/datagenerator/handlers/PaymentFiat.java rename src/main/java/io/skodjob/{loadgenerator => datagenerator}/handlers/Payroll.java (85%) create mode 100644 src/main/java/io/skodjob/datagenerator/handlers/StarGate.java create mode 100644 src/main/java/io/skodjob/datagenerator/handlers/StarWars.java delete mode 100644 src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java create mode 100644 src/test/java/io/skodjob/datagenerator/DataGeneratorTest.java delete mode 100644 src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java diff --git a/pom.xml b/pom.xml index b77d4bc..a11a313 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 io.skodjob - load-generator + data-generator 0.0.1-SNAPSHOT @@ -15,26 +15,26 @@ - load-generator - Reasonable load generator for Messaging - https://github.com/skodjob/load-generator + data-generator + Reasonable data generator for Messaging + https://github.com/skodjob/data-generator - scm:git:git:/github.com/skodjob/load-generator.git - scm:git:ssh://github.com/skodjob/load-generator.git - https://github.com/skodjob/load-generator + scm:git:git:/github.com/skodjob/data-generator.git + scm:git:ssh://github.com/skodjob/data-generator.git + https://github.com/skodjob/data-generator GitHub - https://github.com/skodjob/load-generator/issues + https://github.com/skodjob/data-generator/issues github GitHub Apache Maven Packages - https://maven.pkg.github.com/skodjob/load-generator + https://maven.pkg.github.com/skodjob/data-generator diff --git a/src/main/java/io/skodjob/loadgenerator/DataGenerator.java b/src/main/java/io/skodjob/datagenerator/DataGenerator.java similarity index 66% rename from src/main/java/io/skodjob/loadgenerator/DataGenerator.java rename to src/main/java/io/skodjob/datagenerator/DataGenerator.java index 384db7c..08a758f 100644 --- a/src/main/java/io/skodjob/loadgenerator/DataGenerator.java +++ b/src/main/java/io/skodjob/datagenerator/DataGenerator.java @@ -2,13 +2,17 @@ * Copyright Skodjob authors. * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). */ -package io.skodjob.loadgenerator; +package io.skodjob.datagenerator; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import io.skodjob.loadgenerator.enums.ETemplateType; -import io.skodjob.loadgenerator.handlers.IotDevice; -import io.skodjob.loadgenerator.handlers.Payroll; +import io.skodjob.datagenerator.enums.ETemplateType; +import io.skodjob.datagenerator.handlers.Flights; +import io.skodjob.datagenerator.handlers.IotDevice; +import io.skodjob.datagenerator.handlers.PaymentFiat; +import io.skodjob.datagenerator.handlers.Payroll; +import io.skodjob.datagenerator.handlers.StarGate; +import io.skodjob.datagenerator.handlers.StarWars; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -39,10 +43,18 @@ public DataGenerator(ETemplateType templateType) { */ public String generateStringData() { switch (this.templateType) { - case PAYROLL_EMPLOYEE: + case PAYROLL: return Payroll.generateData(); case IOT_DEVICE: return IotDevice.generateData(); + case STARGATE: + return StarGate.generateData(); + case STARWARS: + return StarWars.generateData(); + case PAYMENT_FIAT: + return PaymentFiat.generateData(); + case FLIGHTS: + return Flights.generateData(); default: throw new IllegalArgumentException("Unknown template type: " + this.templateType); } @@ -60,4 +72,13 @@ public JsonNode generateJsonData() { throw new RuntimeException("Error generating JSON data", e); } } + + /** + * Return template type ued within the generator + * + * @return templateType + */ + public ETemplateType getTemplateType() { + return templateType; + } } diff --git a/src/main/java/io/skodjob/datagenerator/enums/ETemplateType.java b/src/main/java/io/skodjob/datagenerator/enums/ETemplateType.java new file mode 100644 index 0000000..869f078 --- /dev/null +++ b/src/main/java/io/skodjob/datagenerator/enums/ETemplateType.java @@ -0,0 +1,67 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.datagenerator.enums; + +import io.skodjob.datagenerator.handlers.Flights; +import io.skodjob.datagenerator.handlers.IotDevice; +import io.skodjob.datagenerator.handlers.PaymentFiat; +import io.skodjob.datagenerator.handlers.Payroll; +import io.skodjob.datagenerator.handlers.StarGate; +import io.skodjob.datagenerator.handlers.StarWars; + +/** + * Enum representing different template types for use in the load generator. + */ +public enum ETemplateType { + /** + * Template for People Payrol data + */ + PAYROLL(Payroll.TEMPLATE_NAME), + + /** + * Template for IoT device data + */ + IOT_DEVICE(IotDevice.TEMPLATE_NAME), + + /** + * Template for StarGate data + */ + STARGATE(StarGate.TEMPLATE_NAME), + + /** + * Template for StarWars data + */ + STARWARS(StarWars.TEMPLATE_NAME), + + /** + * Template for Payment data + */ + PAYMENT_FIAT(PaymentFiat.TEMPLATE_NAME), + + /** + * Template for Flights data + */ + FLIGHTS(Flights.TEMPLATE_NAME); + + private final String templateName; + + /** + * Constructor for ETemplateType. + * + * @param templateName the name of the template + */ + ETemplateType(String templateName) { + this.templateName = templateName; + } + + /** + * Gets the name of the template. + * + * @return the name of the template + */ + public String getTemplateName() { + return templateName; + } +} diff --git a/src/main/java/io/skodjob/datagenerator/handlers/Flights.java b/src/main/java/io/skodjob/datagenerator/handlers/Flights.java new file mode 100644 index 0000000..bf9d8a2 --- /dev/null +++ b/src/main/java/io/skodjob/datagenerator/handlers/Flights.java @@ -0,0 +1,77 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.datagenerator.handlers; + +import net.datafaker.Faker; + +import java.time.ZoneOffset; +import java.util.Locale; + +/** + * This class is responsible for generating flight data using the Faker library. + */ +public class Flights { + + /** + * Private constructor to make class static + */ + private Flights() { + + } + + private static final Faker FAKER = new Faker(); + + /** + * Template name used in the generator + */ + public static final String TEMPLATE_NAME = "flights"; + + /** + * Generates flight data using the Faker library. + * + * @return the generated flight data as a JSON string + */ + public static String generateData() { + String passengerId = FAKER.idNumber().valid(); + String passengerName = FAKER.name().fullName(); + String passportNumber = FAKER.regexify("[A-Z]{2}[0-9]{6}"); + String nationality = FAKER.nation().nationality(); + String flightNumber = FAKER.regexify("[A-Z]{2}[0-9]{4}"); + String departureAirport = FAKER.aviation().airport(); + String arrivalAirport = FAKER.aviation().airport(); + String departureTime = FAKER.timeAndDate().future(1, java.util.concurrent.TimeUnit.DAYS) + .atOffset(ZoneOffset.UTC).toString(); + String arrivalTime = FAKER.timeAndDate().future(2, java.util.concurrent.TimeUnit.DAYS) + .atOffset(ZoneOffset.UTC).toString(); + String seatNumber = FAKER.regexify("[A-Z][0-9]{2}"); + String gate = FAKER.regexify("[A-Z][0-9]{1,2}"); + String boardingGroup = FAKER.options().option("A", "B", "C", "D", "E", "F"); + String planeModel = FAKER.aviation().aircraft(); + String airline = FAKER.aviation().airline(); + + return String.format(Locale.US, + "{\"passenger\":{" + + "\"id\":\"%s\"," + + "\"name\":\"%s\"," + + "\"passport_number\":\"%s\"," + + "\"nationality\":\"%s\"" + + "}," + + "\"flight\":{" + + "\"number\":\"%s\"," + + "\"departure_airport\":\"%s\"," + + "\"arrival_airport\":\"%s\"," + + "\"departure_time\":\"%s\"," + + "\"arrival_time\":\"%s\"," + + "\"seat_number\":\"%s\"," + + "\"gate\":\"%s\"," + + "\"boarding_group\":\"%s\"," + + "\"plane_model\":\"%s\"," + + "\"airline\":\"%s\"" + + "}}", + passengerId, passengerName, passportNumber, nationality, + flightNumber, departureAirport, arrivalAirport, departureTime, arrivalTime, seatNumber, gate, boardingGroup, + planeModel, airline); + } +} diff --git a/src/main/java/io/skodjob/loadgenerator/handlers/IotDevice.java b/src/main/java/io/skodjob/datagenerator/handlers/IotDevice.java similarity index 94% rename from src/main/java/io/skodjob/loadgenerator/handlers/IotDevice.java rename to src/main/java/io/skodjob/datagenerator/handlers/IotDevice.java index 3bac317..116dd9f 100644 --- a/src/main/java/io/skodjob/loadgenerator/handlers/IotDevice.java +++ b/src/main/java/io/skodjob/datagenerator/handlers/IotDevice.java @@ -2,7 +2,7 @@ * Copyright Skodjob authors. * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). */ -package io.skodjob.loadgenerator.handlers; +package io.skodjob.datagenerator.handlers; import net.datafaker.Faker; @@ -12,8 +12,21 @@ * This class is responsible for generating IoT device data using the Faker library. */ public class IotDevice { + + /** + * Private constructor to make class static + */ + private IotDevice() { + + } + private static final Faker FAKER = new Faker(); + /** + * Template name used in the generator + */ + public static final String TEMPLATE_NAME = "iot_device"; + private static final String TYPE_LIGHT = "light"; private static final String TYPE_BUTTON = "button"; private static final String TYPE_THERMOMETER = "thermometer"; diff --git a/src/main/java/io/skodjob/datagenerator/handlers/PaymentFiat.java b/src/main/java/io/skodjob/datagenerator/handlers/PaymentFiat.java new file mode 100644 index 0000000..3491315 --- /dev/null +++ b/src/main/java/io/skodjob/datagenerator/handlers/PaymentFiat.java @@ -0,0 +1,191 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.datagenerator.handlers; + +import net.datafaker.Faker; + +import java.time.ZoneOffset; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +/** + * This class is responsible for generating payment data using the Faker library. + */ +public class PaymentFiat { + + /** + * Private constructor to make class static + */ + private PaymentFiat() { + + } + + private static final Faker FAKER = new Faker(); + + /** + * Template name used in the generator + */ + public static final String TEMPLATE_NAME = "payment_data"; + + // Constants for payment types + private static final String PAYMENT_TYPE_CREDIT_CARD = "credit_card"; + private static final String PAYMENT_TYPE_BANK_TRANSFER = "bank_transfer"; + private static final String PAYMENT_TYPE_PAYPAL = "paypal"; + + // Constants for payment statuses + private static final String STATUS_COMPLETED = "completed"; + private static final String STATUS_PENDING = "pending"; + private static final String STATUS_FAILED = "failed"; + + // Constants for credit card types + private static final String CARD_TYPE_VISA = "Visa"; + private static final String CARD_TYPE_MASTERCARD = "MasterCard"; + private static final String CARD_TYPE_AMERICAN_EXPRESS = "American Express"; + private static final String CARD_TYPE_REVOLUT = "Revolut"; + private static final String CARD_TYPE_WISE = "Wise"; + private static final String CARD_TYPE_CITYGROUP = "CityGroup"; + private static final String CARD_TYPE_BARCLAYS = "Barclays"; + + // Constants for payer/payee type + private static final String COMPANY = "company"; + private static final String PERSON = "person"; + + // List of world banks + private static final List BANKS = Arrays.asList( + "JPMorgan Chase", "Bank of America", "Wells Fargo", "Citigroup", "Goldman Sachs", + "Morgan Stanley", "HSBC", "BNP Paribas", "UBS", "Credit Suisse", + "Barclays", "Deutsche Bank", "Standard Chartered", "Santander", "Societe Generale", + "ING Group", "Mitsubishi UFJ Financial Group", "Mizuho Financial Group", "Sumitomo Mitsui Financial Group", + "Bank of China", "Industrial and Commercial Bank of China", "China Construction Bank", + "Agricultural Bank of China", "Banco Bradesco", "Itau Unibanco", + "Royal Bank of Canada", "Toronto-Dominion Bank", "National Australia Bank", "Westpac", "ANZ" + ); + + /** + * Generates payment data using the Faker library. + * + * @return the generated payment data as a JSON string + */ + public static String generateData() { + String transactionId = FAKER.regexify("txn_[0-9]{10}"); + String paymentType = FAKER.options() + .option(PAYMENT_TYPE_CREDIT_CARD, PAYMENT_TYPE_BANK_TRANSFER, PAYMENT_TYPE_PAYPAL); + double amount = FAKER.number().randomDouble(2, 10, 1000); + String currency = FAKER.money().currencyCode(); + String date = FAKER.timeAndDate().past(1, java.util.concurrent.TimeUnit.DAYS) + .atOffset(ZoneOffset.UTC).toString(); + String status = FAKER.options().option(STATUS_COMPLETED, STATUS_PENDING, STATUS_FAILED); + + String payerName, payerType, payeeName, payeeType; + + switch (FAKER.number().numberBetween(0, 4)) { + case 0: + payerName = FAKER.company().name(); + payerType = COMPANY; + payeeName = FAKER.company().name(); + payeeType = COMPANY; + break; + case 1: + payerName = FAKER.name().fullName(); + payerType = PERSON; + payeeName = FAKER.company().name(); + payeeType = COMPANY; + break; + case 2: + payerName = FAKER.company().name(); + payerType = COMPANY; + payeeName = FAKER.name().fullName(); + payeeType = PERSON; + break; + default: + payerName = FAKER.name().fullName(); + payerType = PERSON; + payeeName = FAKER.name().fullName(); + payeeType = PERSON; + break; + } + + String payerAccountNumber = FAKER.number().digits(9); + String payerBank = FAKER.options().nextElement(BANKS); + String payerStreet = FAKER.address().streetAddress(); + String payerCity = FAKER.address().city(); + String payerState = FAKER.address().state(); + String payerCountry = FAKER.address().country(); + String payerPostalCode = FAKER.address().zipCode(); + + String payeeAccountNumber = FAKER.number().digits(9); + String payeeBank = FAKER.options().nextElement(BANKS); + String payeeStreet = FAKER.address().streetAddress(); + String payeeCity = FAKER.address().city(); + String payeeState = FAKER.address().state(); + String payeeCountry = FAKER.address().country(); + String payeePostalCode = FAKER.address().zipCode(); + + StringBuilder payerInfo = new StringBuilder(String.format(Locale.US, + "\"name\":\"%s\"," + + "\"payerType\":\"%s\"," + + "\"account_number\":\"%s\"," + + "\"bank\":\"%s\"," + + "\"billing_address\":{" + + "\"street\":\"%s\"," + + "\"city\":\"%s\"," + + "\"state\":\"%s\"," + + "\"country\":\"%s\"," + + "\"postal_code\":\"%s\"" + + "}", + payerName, payerType, payerAccountNumber, payerBank, + payerStreet, payerCity, payerState, payerCountry, payerPostalCode)); + + StringBuilder payeeInfo = new StringBuilder(String.format(Locale.US, + "\"name\":\"%s\"," + + "\"payeeType\":\"%s\"," + + "\"account_number\":\"%s\"," + + "\"bank\":\"%s\"," + + "\"address\":{" + + "\"street\":\"%s\"," + + "\"city\":\"%s\"," + + "\"state\":\"%s\"," + + "\"country\":\"%s\"," + + "\"postal_code\":\"%s\"" + + "}", + payeeName, payeeType, payeeAccountNumber, payeeBank, + payeeStreet, payeeCity, payeeState, payeeCountry, payeePostalCode)); + + if (PAYMENT_TYPE_CREDIT_CARD.equals(paymentType)) { + String payerCardNumber = FAKER.finance().creditCard(); + String payerCardType = FAKER.options().option(CARD_TYPE_VISA, CARD_TYPE_MASTERCARD, + CARD_TYPE_AMERICAN_EXPRESS, CARD_TYPE_REVOLUT, CARD_TYPE_WISE, + CARD_TYPE_CITYGROUP, CARD_TYPE_BARCLAYS); + String payerExpiryDate = FAKER.business().creditCardExpiry(); + + payerInfo.append(String.format(Locale.US, + "," + + "\"card_number\":\"%s\"," + + "\"card_type\":\"%s\"," + + "\"expiry_date\":\"%s\"", + payerCardNumber, payerCardType, payerExpiryDate)); + } + + return String.format(Locale.US, + "{\"payment\":{" + + "\"transaction_id\":\"%s\"," + + "\"type\":\"%s\"," + + "\"amount\":%.2f," + + "\"currency\":\"%s\"," + + "\"date\":\"%s\"," + + "\"status\":\"%s\"" + + "}," + + "\"payer\":{" + + "%s" + + "}," + + "\"payee\":{" + + "%s" + + "}}", + transactionId, paymentType, amount, currency, date, status, + payerInfo, + payeeInfo); + } +} diff --git a/src/main/java/io/skodjob/loadgenerator/handlers/Payroll.java b/src/main/java/io/skodjob/datagenerator/handlers/Payroll.java similarity index 85% rename from src/main/java/io/skodjob/loadgenerator/handlers/Payroll.java rename to src/main/java/io/skodjob/datagenerator/handlers/Payroll.java index e66acf3..f93d6ca 100644 --- a/src/main/java/io/skodjob/loadgenerator/handlers/Payroll.java +++ b/src/main/java/io/skodjob/datagenerator/handlers/Payroll.java @@ -2,7 +2,7 @@ * Copyright Skodjob authors. * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). */ -package io.skodjob.loadgenerator.handlers; +package io.skodjob.datagenerator.handlers; import net.datafaker.Faker; @@ -12,8 +12,21 @@ * This class generates random people-related data for use in templates. */ public class Payroll { + + /** + * Private constructor to make class static + */ + private Payroll() { + + } + private static final Faker FAKER = new Faker(); + /** + * Template name used in the generator + */ + public static final String TEMPLATE_NAME = "payroll"; + /** * Generates payroll employee data using the Faker library. * diff --git a/src/main/java/io/skodjob/datagenerator/handlers/StarGate.java b/src/main/java/io/skodjob/datagenerator/handlers/StarGate.java new file mode 100644 index 0000000..b0d7ca6 --- /dev/null +++ b/src/main/java/io/skodjob/datagenerator/handlers/StarGate.java @@ -0,0 +1,54 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.datagenerator.handlers; + +import net.datafaker.Faker; + +import java.util.Locale; + +/** + * This class generates random StarGate-related data for use in templates. + */ +public class StarGate { + + /** + * Private constructor to make class static + */ + private StarGate() { + + } + + private static final Faker FAKER = new Faker(); + + /** + * Template name used in the generator + */ + public static final String TEMPLATE_NAME = "stargate"; + + /** + * Generates StarGate data using the Faker library. + * + * @return the generated StarGate data as a JSON string + */ + public static String generateData() { + String characterName = FAKER.stargate().characters(); + String sourcePlanet = FAKER.stargate().planets(); + String targetPlanet = FAKER.stargate().planets(); + String quote = FAKER.stargate().quotes(); + int duration = FAKER.number().numberBetween(1, 50); + int distance = FAKER.number().numberBetween(20000, 999999); + + return String.format(Locale.US, + "{\"character_name\":\"%s\"," + + "\"source_planet\":\"%s\"," + + "\"target_planet\":\"%s\"," + + "\"quote\":\"%s\"," + + "\"duration\":%d," + + "\"duration_unit\":\"seconds\"," + + "\"distance\":\"%s\"," + + "\"distance_unit\":\"light_year\"}", + characterName, sourcePlanet, targetPlanet, quote, duration, distance); + } +} diff --git a/src/main/java/io/skodjob/datagenerator/handlers/StarWars.java b/src/main/java/io/skodjob/datagenerator/handlers/StarWars.java new file mode 100644 index 0000000..f6a8119 --- /dev/null +++ b/src/main/java/io/skodjob/datagenerator/handlers/StarWars.java @@ -0,0 +1,59 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.datagenerator.handlers; + +import net.datafaker.Faker; + +import java.util.Locale; + +/** + * This class generates random StarWars-related data for use in templates. + */ +public class StarWars { + + /** + * Private constructor to make class static + */ + private StarWars() { + + } + + private static final Faker FAKER = new Faker(); + + /** + * Template name used in the generator + */ + public static final String TEMPLATE_NAME = "starwars"; + + /** + * Generates StarWars data using the Faker library. + * + * @return the generated StarWars data as a JSON string + */ + public static String generateData() { + String characterName = FAKER.starWars().character(); + String sourcePlanet = FAKER.starWars().planets(); + String targetPlanet = FAKER.starWars().planets(); + String quote = FAKER.starWars().quotes(); + String callSign = FAKER.starWars().callSign(); + String species = FAKER.starWars().species(); + String vehicle = FAKER.starWars().vehicles(); + String wookieWords = FAKER.starWars().wookieWords(); + String alternateCharacterSpelling = FAKER.starWars().alternateCharacterSpelling(); + + return String.format(Locale.US, + "{\"character_name\":\"%s\"," + + "\"source_planet\":\"%s\"," + + "\"target_planet\":\"%s\"," + + "\"quote\":\"%s\"," + + "\"callSign\":\"%s\"," + + "\"species\":\"%s\"," + + "\"vehicle\":\"%s\"," + + "\"wookieWords\":\"%s\"," + + "\"alternateCharacterSpelling\":\"%s\"}", + characterName, sourcePlanet, targetPlanet, quote, callSign, species, + vehicle, wookieWords, alternateCharacterSpelling); + } +} diff --git a/src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java b/src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java deleted file mode 100644 index 6cda6ab..0000000 --- a/src/main/java/io/skodjob/loadgenerator/enums/ETemplateType.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Skodjob authors. - * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). - */ -package io.skodjob.loadgenerator.enums; - -/** - * Enum representing different template types for use in the load generator. - */ -public enum ETemplateType { - /** - * Template for People Payrol data - */ - PAYROLL_EMPLOYEE("payroll_employee"), - - /** - * Template for IoT device data - */ - IOT_DEVICE("iot_device"); - - private final String templateName; - - /** - * Constructor for ETemplateType. - * - * @param templateName the name of the template - */ - ETemplateType(String templateName) { - this.templateName = templateName; - } - - /** - * Gets the name of the template. - * - * @return the name of the template - */ - public String getTemplateName() { - return templateName; - } -} diff --git a/src/test/java/io/skodjob/datagenerator/DataGeneratorTest.java b/src/test/java/io/skodjob/datagenerator/DataGeneratorTest.java new file mode 100644 index 0000000..2569455 --- /dev/null +++ b/src/test/java/io/skodjob/datagenerator/DataGeneratorTest.java @@ -0,0 +1,174 @@ +/* + * Copyright Skodjob authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.skodjob.datagenerator; + +import com.fasterxml.jackson.databind.JsonNode; +import io.skodjob.datagenerator.enums.ETemplateType; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class DataGeneratorTest { + private DataGenerator payrollDataGenerator; + private DataGenerator iotDataGenerator; + private DataGenerator stargateDataGenerator; + private DataGenerator starwarsDataGenerator; + private DataGenerator paymentFiatGenerator; + private DataGenerator flightsGenerator; + + @BeforeAll + void setUp() { + payrollDataGenerator = new DataGenerator(ETemplateType.PAYROLL); + iotDataGenerator = new DataGenerator(ETemplateType.IOT_DEVICE); + stargateDataGenerator = new DataGenerator(ETemplateType.STARGATE); + starwarsDataGenerator = new DataGenerator(ETemplateType.STARWARS); + paymentFiatGenerator = new DataGenerator(ETemplateType.PAYMENT_FIAT); + flightsGenerator = new DataGenerator(ETemplateType.FLIGHTS); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("testRepeatedParameters") + void testValidateGeneratedData(String testName, String regex, DataGenerator generator) { + Pattern dataPattern = Pattern.compile(regex); + + String data = generator.generateStringData(); + assertNotNull(data, "Generated string data should not be null for PAYROLL_EMPLOYEE"); + + Matcher matcher = dataPattern.matcher(data); + assertTrue(matcher.matches(), "Generated data doesn't match the expected format!"); + } + + @Test + void testGenerateJsonData() { + checkJsonData(payrollDataGenerator); + checkJsonData(iotDataGenerator); + checkJsonData(stargateDataGenerator); + checkJsonData(starwarsDataGenerator); + checkJsonData(paymentFiatGenerator); + checkJsonData(flightsGenerator); + } + + void checkJsonData(DataGenerator generator) { + JsonNode jsonData = generator.generateJsonData(); + assertNotNull(jsonData, "Generated JSON data should not be null for " + generator.getTemplateType()); + assertTrue(jsonData.isObject(), "Generated JSON data should be a JSON object for " + generator.getTemplateType()); + } + + public Stream testRepeatedParameters() { + String peopleRegex = "\\{" + + "\"employee_id\":\"\\d+\"," + + "\"first_name\":\"[A-Za-z']+\"," + + "\"last_name\":\"[A-Za-z']+\"," + + "\"age\":\\d+," + + "\"ssn\":\"\\d+-\\d+-\\d+\"," + + "\"hourly_rate\":\\d+\\.\\d+," + + "\"gender\":\"(Male|Female)\"," + + "\"email\":\"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\"," + + "\"company\":\"[A-Za-z-&\\.\\,\\-' ]+\"" + + "\\}"; + + String iotRegex = "\\{" + + "\"IPV4\":\"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\"," + + "\"MAC\":\"([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\"," + + "\"ID\":\"\\d+\"," + + "\"TYPE\":\"(light|button|thermometer|plug|custom|gate)\"," + + "\"LAST_UPDATE\":\"\\d+\"," + + "\"LINK_QUALITY\":\\d{1,3}," + + "\"DATA\":\\{.*\\}" + + "\\}"; + + String starGateRegex = "\\{\"character_name\":\"[\\w\\s'-]+\"," + + "\"source_planet\":\"[\\w\\s-]+\"," + + "\"target_planet\":\"[\\w\\s-]+\"," + + "\"quote\":\"[^\"]*\"," + + "\"duration\":[0-9]+," + + "\"duration_unit\":\"seconds\"," + + "\"distance\":\"[0-9]+\"," + + "\"distance_unit\":\"light_year\"\\}"; + + String starWarsRegex = "\\{\"character_name\":\"[\\w\\s'-]+\"," + + "\"source_planet\":\"[\\w\\s-]+\"," + + "\"target_planet\":\"[\\w\\s-]+\"," + + "\"quote\":\"[^\"]*\"," + + "\"callSign\":\"[\\w\\s\\-]+\"," + + "\"species\":\"[\\w\\s'-]+\"," + + "\"vehicle\":\"[\\w\\s\\-']+\"," + + "\"wookieWords\":\"[^\"]*\"," + + "\"alternateCharacterSpelling\":\"[^\"]*\"\\}"; + + String paymentFiatRegex = "\\{\"payment\":\\{\"transaction_id\":\"txn_[0-9]{10}\"," + + "\"type\":\"(credit_card|bank_transfer|paypal)\"," + + "\"amount\":[0-9]+\\.[0-9]{2}," + + "\"currency\":\"[A-Z]{1,}\"," + + "\"date\":\"[0-9T:\\-\\+\\.Z]+\"," + + "\"status\":\"(completed|pending|failed)\"\\}," + + "\"payer\":\\{\"name\":\"[^\"]{3,}\"," + + "\"payerType\":\"(company|person)\"," + + "\"account_number\":\"[0-9]{9}\"," + + "\"bank\":\"[^\"]{3,}\"," + + "\"billing_address\":\\{\"street\":\"[^\"]{3,}\"," + + "\"city\":\"[^\"]{3,}\"," + + "\"state\":\"[^\"]{3,}\"," + + "\"country\":\"[^\"]{3,}\"," + + "\"postal_code\":\"[^\"]{3,}\"\\}" + + "(,\"card_number\":\"[0-9\\-]+\"," + + "\"card_type\":\"(Visa|MasterCard|American Express|Revolut|Wise|CityGroup|Barclays)\"," + + "\"expiry_date\":\"[0-9\\-]+\")?\\}," + + "\"payee\":\\{\"name\":\"[^\"]{3,}\"," + + "\"payeeType\":\"(company|person)\"," + + "\"account_number\":\"[0-9]{9}\"," + + "\"bank\":\"[^\"]{3,}\"," + + "\"address\":\\{\"street\":\"[^\"]{3,}\"," + + "\"city\":\"[^\"]{3,}\"," + + "\"state\":\"[^\"]{3,}\"," + + "\"country\":\"[^\"]{3,}\"," + + "\"postal_code\":\"[^\"]{3,}\"\\}\\}\\}"; + + String flightRegex = "\\{" + + "\"passenger\":\\{" + + "\"id\":\"[A-Z0-9\\-]+\"," + + "\"name\":\"[^\"]{4,}\"," + + "\"passport_number\":\"[A-Z]{2}[0-9]{6}\"," + + "\"nationality\":\"[^\"]{2,}\"\\}," + + "\"flight\":\\{\"number\":\"[A-Z]{2}[0-9]{4}\"," + + "\"departure_airport\":\"[\\w\\s]+\"," + + "\"arrival_airport\":\"[\\w\\s]+\"," + + "\"departure_time\":\"[0-9T:\\-\\+\\.Z]+\"," + + "\"arrival_time\":\"[0-9T:\\-\\+\\.Z]+\"," + + "\"seat_number\":\"[A-Z][0-9]{2}\"," + + "\"gate\":\"[A-Z][0-9]{1,2}\"," + + "\"boarding_group\":\"[A-F]\"," + + "\"plane_model\":\"[^\"]{4,}\"," + + "\"airline\":\"[^\"]{4,}\"\\}\\}"; + + return IntStream.range(0, 10000) + .mapToObj(i -> Stream.of( + Arguments.of(ETemplateType.PAYROLL.getTemplateName(), peopleRegex, + this.payrollDataGenerator), + Arguments.of(ETemplateType.IOT_DEVICE.getTemplateName(), iotRegex, + this.iotDataGenerator), + Arguments.of(ETemplateType.STARGATE.getTemplateName(), starGateRegex, + this.stargateDataGenerator), + Arguments.of(ETemplateType.STARWARS.getTemplateName(), starWarsRegex, + this.starwarsDataGenerator), + Arguments.of(ETemplateType.PAYMENT_FIAT.getTemplateName(), paymentFiatRegex, + this.paymentFiatGenerator), + Arguments.of(ETemplateType.FLIGHTS.getTemplateName(), flightRegex, + this.flightsGenerator) + )) + .flatMap(stream -> stream); + } +} diff --git a/src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java b/src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java deleted file mode 100644 index 4d4fa7b..0000000 --- a/src/test/java/io/skodjob/loadgenerator/DataGeneratorTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright Skodjob authors. - * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). - */ -package io.skodjob.loadgenerator; - -import com.fasterxml.jackson.databind.JsonNode; -import io.skodjob.loadgenerator.enums.ETemplateType; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - -class DataGeneratorTest { - private DataGenerator payrollDataGenerator; - private DataGenerator iotDataGenerator; - - @BeforeEach - void setUp() { - payrollDataGenerator = new DataGenerator(ETemplateType.PAYROLL_EMPLOYEE); - iotDataGenerator = new DataGenerator(ETemplateType.IOT_DEVICE); - } - - @ParameterizedTest(name = "{0}") - @MethodSource("testRepeatedParameters") - void testValidateGeneratedData(String testName, String regex, DataGenerator generator) { - Pattern dataPattern = Pattern.compile(regex); - - String data = generator.generateStringData(); - assertNotNull(data, "Generated string data should not be null for PAYROLL_EMPLOYEE"); - assertFalse(data.contains("\"@"), "Generated string data should not contain placeholders for PAYROLL_EMPLOYEE"); - - Matcher matcher = dataPattern.matcher(data); - assertTrue(matcher.matches(), "Generated data doesn't match the expected format!"); - } - - @Test - void testGenerateJsonDataPayroll() throws IOException { - JsonNode jsonData = payrollDataGenerator.generateJsonData(); - assertNotNull(jsonData, "Generated JSON data should not be null for PAYROLL_EMPLOYEE"); - assertTrue(jsonData.isObject(), "Generated JSON data should be a JSON object for PAYROLL_EMPLOYEE"); - } - - @Test - void testGenerateJsonDataIot() throws IOException { - JsonNode jsonData = iotDataGenerator.generateJsonData(); - assertNotNull(jsonData, "Generated JSON data should not be null for IOT_DEVICE"); - assertTrue(jsonData.isObject(), "Generated JSON data should be a JSON object for IOT_DEVICE"); - } - - @Test - void testInvalidTemplateType() { - NullPointerException thrown = assertThrows(NullPointerException.class, () -> { - DataGenerator invalidDataGenerator = new DataGenerator(null); - invalidDataGenerator.generateStringData(); - }, "Expected generateStringData() to throw an exception, but it didn't"); - - assertTrue(thrown.getMessage().contains("TemplateType cannot be null!"), "Exception message should contain 'TemplateType cannot be null!'"); - } - - public static Stream testRepeatedParameters() { - String peopleRegex = "\\{" - + "\"employee_id\":\"\\d+\"," - + "\"first_name\":\"[A-Za-z']+\"," - + "\"last_name\":\"[A-Za-z']+\"," - + "\"age\":\\d+," - + "\"ssn\":\"\\d+-\\d+-\\d+\"," - + "\"hourly_rate\":\\d+\\.\\d+," - + "\"gender\":\"(Male|Female)\"," - + "\"email\":\"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\"," - + "\"company\":\"[A-Za-z-&\\.\\,\\-' ]+\"" - + "\\}"; - - String iotRegex = "\\{" - + "\"IPV4\":\"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\"," - + "\"MAC\":\"([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\"," - + "\"ID\":\"\\d+\"," - + "\"TYPE\":\"(light|button|thermometer|plug|custom|gate)\"," - + "\"LAST_UPDATE\":\"\\d+\"," - + "\"LINK_QUALITY\":\\d{1,3}," - + "\"DATA\":\\{.*\\}" - + "\\}"; - - - return IntStream.range(0, 10000) - .mapToObj(i -> Stream.of( - Arguments.of(ETemplateType.PAYROLL_EMPLOYEE.getTemplateName(), peopleRegex, - new DataGenerator(ETemplateType.PAYROLL_EMPLOYEE)), - Arguments.of(ETemplateType.IOT_DEVICE.getTemplateName(), iotRegex, - new DataGenerator(ETemplateType.IOT_DEVICE)) - )) - .flatMap(stream -> stream); - } -}