From 6fb1b11b9bd50f93828c9252418b7b20aab62dcf Mon Sep 17 00:00:00 2001 From: Prudhvi Godithi Date: Sun, 28 Apr 2024 16:51:38 -0700 Subject: [PATCH] Imporve plugin Code Coverage Signed-off-by: Prudhvi Godithi --- .github/workflows/ci.yml | 6 +- build.gradle | 1 + .../jobscheduler/JobSchedulerPlugin.java | 9 +- .../jobscheduler/model/JobDetails.java | 1 - .../jobscheduler/JobSchedulerPluginTests.java | 190 ++++++++++++++++++ .../ScheduledJobProviderTests.java | 63 ++++++ .../model/ExtensionJobParameterTests.java | 185 +++++++++++++++++ .../jobscheduler/model/JobDetailsTests.java | 174 ++++++++++++++++ .../utils/JobDetailsServiceIT.java | 3 +- 9 files changed, 626 insertions(+), 6 deletions(-) create mode 100644 src/test/java/org/opensearch/jobscheduler/JobSchedulerPluginTests.java create mode 100644 src/test/java/org/opensearch/jobscheduler/ScheduledJobProviderTests.java create mode 100644 src/test/java/org/opensearch/jobscheduler/model/ExtensionJobParameterTests.java create mode 100644 src/test/java/org/opensearch/jobscheduler/model/JobDetailsTests.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51b6fd47..b98f8b92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: su `id -un 1000` -c "./gradlew build && ./gradlew publishToMavenLocal" - name: Upload Coverage Report - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -84,7 +84,7 @@ jobs: ./gradlew publishToMavenLocal - name: Upload Coverage Report - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -124,7 +124,7 @@ jobs: ./gradlew.bat publishToMavenLocal - name: Upload Coverage Report - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/build.gradle b/build.gradle index fd4eac51..b0fa5878 100644 --- a/build.gradle +++ b/build.gradle @@ -162,6 +162,7 @@ dependencies { implementation project(path: ":${rootProject.name}-spi", configuration: 'shadow') implementation group: 'com.google.guava', name: 'guava', version:'32.1.3-jre' implementation group: 'com.google.guava', name: 'failureaccess', version:'1.0.2' + testImplementation group: 'org.mockito', name: 'mockito-core', version: '5.11.0' javaRestTestImplementation project.sourceSets.main.runtimeClasspath //spotless implementation('com.google.googlejavaformat:google-java-format:1.22.0') { diff --git a/src/main/java/org/opensearch/jobscheduler/JobSchedulerPlugin.java b/src/main/java/org/opensearch/jobscheduler/JobSchedulerPlugin.java index 96d7eddc..c305118e 100644 --- a/src/main/java/org/opensearch/jobscheduler/JobSchedulerPlugin.java +++ b/src/main/java/org/opensearch/jobscheduler/JobSchedulerPlugin.java @@ -69,7 +69,6 @@ public class JobSchedulerPlugin extends Plugin implements ActionPlugin, Extensib public static final String JS_BASE_URI = "/_plugins/_job_scheduler"; private static final Logger log = LogManager.getLogger(JobSchedulerPlugin.class); - private JobSweeper sweeper; private JobScheduler scheduler; private LockService lockService; @@ -83,6 +82,14 @@ public JobSchedulerPlugin() { this.indexToJobProviders = new HashMap<>(); } + public Set getIndicesToListen() { + return indicesToListen; + } + + public Map getIndexToJobProviders() { + return indexToJobProviders; + } + @Override public Collection getSystemIndexDescriptors(Settings settings) { return Collections.singletonList( diff --git a/src/main/java/org/opensearch/jobscheduler/model/JobDetails.java b/src/main/java/org/opensearch/jobscheduler/model/JobDetails.java index 19c4011d..8b1ad320 100644 --- a/src/main/java/org/opensearch/jobscheduler/model/JobDetails.java +++ b/src/main/java/org/opensearch/jobscheduler/model/JobDetails.java @@ -95,7 +95,6 @@ public static JobDetails parse(XContentParser parser) throws IOException { String extensionUniqueId = null; ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser); - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { String fieldName = parser.currentName(); parser.nextToken(); diff --git a/src/test/java/org/opensearch/jobscheduler/JobSchedulerPluginTests.java b/src/test/java/org/opensearch/jobscheduler/JobSchedulerPluginTests.java new file mode 100644 index 00000000..ea03e769 --- /dev/null +++ b/src/test/java/org/opensearch/jobscheduler/JobSchedulerPluginTests.java @@ -0,0 +1,190 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.jobscheduler; + +import org.opensearch.Version; +import org.opensearch.cluster.metadata.IndexMetadata; +import org.opensearch.cluster.node.DiscoveryNodes; +import org.opensearch.common.settings.ClusterSettings; +import org.opensearch.common.settings.IndexScopedSettings; +import org.opensearch.common.settings.SettingsFilter; +import org.opensearch.common.unit.TimeValue; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.apache.lucene.tests.index.AssertingDirectoryReader; +import org.junit.Before; +import org.mockito.Mock; +import org.opensearch.cluster.metadata.IndexNameExpressionResolver; +import org.opensearch.common.settings.Setting; +import org.opensearch.common.settings.Settings; +import org.opensearch.core.index.Index; +import org.opensearch.env.Environment; +import org.opensearch.index.IndexModule; +import org.opensearch.index.IndexSettings; +import org.opensearch.index.analysis.AnalysisRegistry; +import org.opensearch.index.engine.EngineConfigFactory; +import org.opensearch.jobscheduler.rest.action.RestGetJobDetailsAction; +import org.opensearch.jobscheduler.rest.action.RestGetLockAction; +import org.opensearch.jobscheduler.rest.action.RestReleaseLockAction; +import org.opensearch.jobscheduler.spi.JobSchedulerExtension; +import org.opensearch.jobscheduler.spi.ScheduledJobParser; +import org.opensearch.jobscheduler.spi.ScheduledJobRunner; +import org.opensearch.jobscheduler.utils.JobDetailsService; +import org.opensearch.plugins.ExtensiblePlugin; +import org.opensearch.rest.RestController; +import org.opensearch.rest.RestHandler; +import org.opensearch.test.IndexSettingsModule; +import org.opensearch.test.OpenSearchTestCase; + +import org.opensearch.test.engine.MockEngineFactory; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.instanceOf; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class JobSchedulerPluginTests extends OpenSearchTestCase { + + private JobSchedulerPlugin plugin; + + private Index index; + private Settings settings; + private Settings sweeperSettings; + private IndexSettings indexSettings; + private IndexModule indexModule; + private AnalysisRegistry emptyAnalysisRegistry; + + @Mock + private RestController restController; + @Mock + private ClusterSettings clusterSettings; + @Mock + private IndexScopedSettings indexScopedSettings; + @Mock + private SettingsFilter settingsFilter; + @Mock + private IndexNameExpressionResolver indexNameExpressionResolver; + @Mock + private Supplier nodesInCluster; + + @Before + public void setup() { + plugin = new JobSchedulerPlugin(); + settings = Settings.builder() + .put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT) + .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) + .build(); + indexSettings = IndexSettingsModule.newIndexSettings(JobDetailsService.JOB_DETAILS_INDEX_NAME, settings); + index = indexSettings.getIndex(); + final MockEngineFactory engineFactory = new MockEngineFactory(AssertingDirectoryReader.class); + indexModule = new IndexModule( + indexSettings, + emptyAnalysisRegistry, + engineFactory, + new EngineConfigFactory(indexSettings), + Collections.emptyMap(), + () -> true, + new IndexNameExpressionResolver(new ThreadContext(Settings.EMPTY)), + Collections.emptyMap() + ); + sweeperSettings = Settings.builder() + .put(JobSchedulerSettings.SWEEP_PERIOD.getKey(), TimeValue.timeValueMinutes(1)) + .put(JobSchedulerSettings.SWEEP_PAGE_SIZE.getKey(), 10) + .put(JobSchedulerSettings.SWEEP_BACKOFF_MILLIS.getKey(), TimeValue.timeValueMillis(100)) + .put(JobSchedulerSettings.SWEEP_BACKOFF_RETRY_COUNT.getKey(), 5) + .build(); + } + + public void testLoadExtensions() { + ExtensiblePlugin.ExtensionLoader mockLoader = mock(ExtensiblePlugin.ExtensionLoader.class); + JobSchedulerExtension mockExtension1 = mock(JobSchedulerExtension.class); + JobSchedulerExtension mockExtension2 = mock(JobSchedulerExtension.class); + when(mockLoader.loadExtensions(JobSchedulerExtension.class)).thenReturn(Arrays.asList(mockExtension1, mockExtension2)); + when(mockExtension1.getJobType()).thenReturn("jobType1"); + when(mockExtension1.getJobIndex()).thenReturn("index1"); + when(mockExtension2.getJobType()).thenReturn("jobType2"); + when(mockExtension2.getJobIndex()).thenReturn("index2"); + ScheduledJobParser mockParser = mock(ScheduledJobParser.class); + ScheduledJobRunner mockRunner = mock(ScheduledJobRunner.class); + when(mockExtension1.getJobParser()).thenReturn(mockParser); + when(mockExtension1.getJobRunner()).thenReturn(mockRunner); + plugin.loadExtensions(mockLoader); + assertEquals(2, plugin.getIndexToJobProviders().size()); + assertTrue(plugin.getIndicesToListen().contains("index1")); + assertTrue(plugin.getIndicesToListen().contains("index2")); + } + + public void testGetSettings_returnsSettingsList() { + List> settings = plugin.getSettings(); + assertNotNull(settings); + assertEquals(12, settings.size()); + assertTrue(settings.contains(LegacyOpenDistroJobSchedulerSettings.SWEEP_PAGE_SIZE)); + assertTrue(settings.contains(LegacyOpenDistroJobSchedulerSettings.REQUEST_TIMEOUT)); + assertTrue(settings.contains(LegacyOpenDistroJobSchedulerSettings.SWEEP_BACKOFF_MILLIS)); + assertTrue(settings.contains(LegacyOpenDistroJobSchedulerSettings.SWEEP_BACKOFF_RETRY_COUNT)); + assertTrue(settings.contains(LegacyOpenDistroJobSchedulerSettings.SWEEP_PERIOD)); + assertTrue(settings.contains(LegacyOpenDistroJobSchedulerSettings.JITTER_LIMIT)); + assertTrue(settings.contains(JobSchedulerSettings.SWEEP_PAGE_SIZE)); + assertTrue(settings.contains(JobSchedulerSettings.REQUEST_TIMEOUT)); + assertTrue(settings.contains(JobSchedulerSettings.SWEEP_BACKOFF_MILLIS)); + assertTrue(settings.contains(JobSchedulerSettings.SWEEP_BACKOFF_RETRY_COUNT)); + assertTrue(settings.contains(JobSchedulerSettings.SWEEP_PERIOD)); + assertTrue(settings.contains(JobSchedulerSettings.JITTER_LIMIT)); + } + + public void testOnIndexModule() { + assertEquals(indexModule.getIndex().toString(), index.toString()); + assertEquals(index.getName(), JobDetailsService.JOB_DETAILS_INDEX_NAME); + } + + public void testGetRestHandlers() { + List restHandlers = plugin.getRestHandlers( + settings, + restController, + clusterSettings, + indexScopedSettings, + settingsFilter, + indexNameExpressionResolver, + nodesInCluster + ); + assertThat( + restHandlers, + containsInAnyOrder( + instanceOf(RestGetJobDetailsAction.class), + instanceOf(RestGetLockAction.class), + instanceOf(RestReleaseLockAction.class) + ) + ); + } + + public void testGetIndicesToListen() { + Set expectedIndices = new HashSet<>(); + expectedIndices.add("index1"); + expectedIndices.add("index2"); + plugin.getIndicesToListen().addAll(expectedIndices); + Set actualIndices = plugin.getIndicesToListen(); + assertEquals(expectedIndices, actualIndices); + } + + public void testGetIndexToJobProviders() { + Map expectedProviders = plugin.getIndexToJobProviders(); + ScheduledJobParser mockParser = mock(ScheduledJobParser.class); + ScheduledJobRunner mockRunner = mock(ScheduledJobRunner.class); + expectedProviders.put("index1", new ScheduledJobProvider("test-job-1", "test-job-index-1", mockParser, mockRunner)); + Map actualProviders = plugin.getIndexToJobProviders(); + assertEquals(expectedProviders, actualProviders); + } +} diff --git a/src/test/java/org/opensearch/jobscheduler/ScheduledJobProviderTests.java b/src/test/java/org/opensearch/jobscheduler/ScheduledJobProviderTests.java new file mode 100644 index 00000000..e1c7769c --- /dev/null +++ b/src/test/java/org/opensearch/jobscheduler/ScheduledJobProviderTests.java @@ -0,0 +1,63 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.jobscheduler; + +import org.junit.Before; +import org.mockito.Mock; +import org.opensearch.jobscheduler.spi.ScheduledJobParser; +import org.opensearch.jobscheduler.spi.ScheduledJobRunner; +import org.opensearch.test.OpenSearchTestCase; + +import static org.mockito.Mockito.mock; + +public class ScheduledJobProviderTests extends OpenSearchTestCase { + + private static final String JOB_TYPE = "test_job_type"; + private static final String JOB_INDEX_NAME = "test_job_index"; + + @Mock + private ScheduledJobParser jobParser; + + @Mock + private ScheduledJobRunner jobRunner; + + private ScheduledJobProvider scheduledJobProvider; + + @Before + public void setUp() throws Exception { + super.setUp(); + scheduledJobProvider = new ScheduledJobProvider(JOB_TYPE, JOB_INDEX_NAME, jobParser, jobRunner); + } + + public void testGetJobType() { + assertEquals(JOB_TYPE, scheduledJobProvider.getJobType()); + } + + public void testGetJobIndexName() { + assertEquals(JOB_INDEX_NAME, scheduledJobProvider.getJobIndexName()); + } + + public void testGetJobParser() { + assertEquals(jobParser, scheduledJobProvider.getJobParser()); + } + + public void testGetJobRunner() { + assertEquals(jobRunner, scheduledJobProvider.getJobRunner()); + } + + public void testConstructor() { + ScheduledJobParser parser = mock(ScheduledJobParser.class); + ScheduledJobRunner runner = mock(ScheduledJobRunner.class); + ScheduledJobProvider provider = new ScheduledJobProvider(JOB_TYPE, JOB_INDEX_NAME, parser, runner); + assertEquals(JOB_TYPE, provider.getJobType()); + assertEquals(JOB_INDEX_NAME, provider.getJobIndexName()); + assertEquals(parser, provider.getJobParser()); + assertEquals(runner, provider.getJobRunner()); + } +} diff --git a/src/test/java/org/opensearch/jobscheduler/model/ExtensionJobParameterTests.java b/src/test/java/org/opensearch/jobscheduler/model/ExtensionJobParameterTests.java new file mode 100644 index 00000000..c4a3a533 --- /dev/null +++ b/src/test/java/org/opensearch/jobscheduler/model/ExtensionJobParameterTests.java @@ -0,0 +1,185 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.jobscheduler.model; + +import org.junit.Before; +import org.opensearch.common.xcontent.XContentFactory; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.jobscheduler.spi.ScheduledJobParameter; +import org.opensearch.jobscheduler.spi.schedule.Schedule; +import org.opensearch.test.OpenSearchTestCase; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Instant; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ExtensionJobParameterTests extends OpenSearchTestCase { + + private String jobName = "testJob"; + Schedule schedule; + private Instant lastUpdateTime = Instant.ofEpochSecond(1609459200); + private Instant enabledTime = Instant.ofEpochSecond(1609459200);; + private boolean isEnabled = true; + private Long lockDurationSeconds = 60L; + private Double jitter = 0.1; + private ExtensionJobParameter extensionJobParameter; + + public ExtensionJobParameterTests() throws IOException {} + + @Before + public void setUp() throws Exception { + super.setUp(); + extensionJobParameter = new ExtensionJobParameter( + jobName, + schedule, + lastUpdateTime, + enabledTime, + isEnabled, + lockDurationSeconds, + jitter + ); + } + + public void testConstructorWithCronSchedule() throws IOException { + String jobName = "testJob"; + Instant lastUpdateTime = Instant.ofEpochSecond(1609459200); + Instant enabledTime = Instant.ofEpochSecond(1609459200); + boolean isEnabled = true; + Long lockDurationSeconds = 60L; + Double jitter = 0.1; + assertEquals(jobName, extensionJobParameter.getName()); + assertEquals(schedule, extensionJobParameter.getSchedule()); + assertEquals(lastUpdateTime, extensionJobParameter.getLastUpdateTime()); + assertEquals(enabledTime, extensionJobParameter.getEnabledTime()); + assertTrue(extensionJobParameter.isEnabled()); + assertEquals(lockDurationSeconds, extensionJobParameter.getLockDurationSeconds()); + assertEquals(jitter, extensionJobParameter.getJitter()); + assertEquals(isEnabled, extensionJobParameter.isEnabled()); + } + + public void testExtensionJobParameterFromScheduledJobParameter() { + String jobName = "test-job"; + Instant lastUpdateTime = Instant.now(); + Instant enabledTime = Instant.now().plusSeconds(3600); + boolean isEnabled = true; + Long lockDurationSeconds = 60L; + Double jitter = 0.5; + ScheduledJobParameter mockJobParameter = mock(ScheduledJobParameter.class); + when(mockJobParameter.getName()).thenReturn(jobName); + when(mockJobParameter.getLastUpdateTime()).thenReturn(lastUpdateTime); + when(mockJobParameter.getEnabledTime()).thenReturn(enabledTime); + when(mockJobParameter.isEnabled()).thenReturn(isEnabled); + when(mockJobParameter.getLockDurationSeconds()).thenReturn(lockDurationSeconds); + when(mockJobParameter.getJitter()).thenReturn(jitter); + ExtensionJobParameter extensionJobParameter = new ExtensionJobParameter(mockJobParameter); + assertEquals(jobName, extensionJobParameter.getName()); + assertEquals(lastUpdateTime, extensionJobParameter.getLastUpdateTime()); + assertEquals(enabledTime, extensionJobParameter.getEnabledTime()); + assertEquals(isEnabled, extensionJobParameter.isEnabled()); + assertEquals(lockDurationSeconds, extensionJobParameter.getLockDurationSeconds()); + assertEquals(jitter, extensionJobParameter.getJitter(), 0.0); + } + + public void testExtensionJobParameterFromScheduledJobParameterWithNullJitter() { + String jobName = "test-job"; + Instant lastUpdateTime = Instant.now(); + Instant enabledTime = Instant.now().plusSeconds(3600); + boolean isEnabled = true; + Long lockDurationSeconds = 60L; + ScheduledJobParameter mockJobParameter = mock(ScheduledJobParameter.class); + when(mockJobParameter.getName()).thenReturn(jobName); + when(mockJobParameter.getLastUpdateTime()).thenReturn(lastUpdateTime); + when(mockJobParameter.getEnabledTime()).thenReturn(enabledTime); + when(mockJobParameter.isEnabled()).thenReturn(isEnabled); + when(mockJobParameter.getLockDurationSeconds()).thenReturn(lockDurationSeconds); + when(mockJobParameter.getJitter()).thenReturn(null); + ExtensionJobParameter extensionJobParameter = new ExtensionJobParameter(mockJobParameter); + assertEquals(0.0, extensionJobParameter.getJitter(), 0.0); + } + + public void testGetName() { + assertEquals(jobName, extensionJobParameter.getName()); + } + + public void testGetLastUpdateTime() { + assertEquals(lastUpdateTime, extensionJobParameter.getLastUpdateTime()); + } + + public void testGetEnabledTime() { + assertEquals(enabledTime, extensionJobParameter.getEnabledTime()); + } + + public void testGetSchedule() { + assertEquals(schedule, extensionJobParameter.getSchedule()); + } + + public void testIsEnabled() { + assertEquals(isEnabled, extensionJobParameter.isEnabled()); + } + + public void testGetLockDurationSeconds() { + assertEquals(lockDurationSeconds, extensionJobParameter.getLockDurationSeconds()); + } + + public void testGetJitter() { + assertEquals(jitter, extensionJobParameter.getJitter()); + } + + public void testToXContent() throws IOException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder(outputStream); + extensionJobParameter.toXContent(xContentBuilder, null); + xContentBuilder.flush(); + String actualOutput = outputStream.toString(StandardCharsets.UTF_8); + String expectedOutput = + "{\"name\":\"testJob\",\"schedule\":null,\"last_update_time\":1609459200000,\"enabled_time\":1609459200000,\"enabled\":true,\"lock_duration_seconds\":60,\"jitter\":0.1}"; + assertEquals(expectedOutput, actualOutput); + } + + public void testExtensionJobParameterConstructor() { + ScheduledJobParameter jobParameter = new ScheduledJobParameter() { + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + return null; + } + + @Override + public String getName() { + return "TestJob"; + } + + @Override + public Instant getLastUpdateTime() { + return null; + } + + @Override + public Instant getEnabledTime() { + return null; + } + + @Override + public Schedule getSchedule() { + return null; + } + + @Override + public boolean isEnabled() { + return false; + } + }; + ExtensionJobParameter extensionJobParameter = new ExtensionJobParameter(jobParameter); + assertEquals("TestJob", extensionJobParameter.getName()); + assertEquals(0.0, extensionJobParameter.getJitter(), 0.01); // We can add a delta for double comparison + } +} diff --git a/src/test/java/org/opensearch/jobscheduler/model/JobDetailsTests.java b/src/test/java/org/opensearch/jobscheduler/model/JobDetailsTests.java new file mode 100644 index 00000000..f2a5a1d0 --- /dev/null +++ b/src/test/java/org/opensearch/jobscheduler/model/JobDetailsTests.java @@ -0,0 +1,174 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.jobscheduler.model; + +import org.junit.Before; +import org.opensearch.common.xcontent.XContentFactory; +import org.opensearch.common.xcontent.XContentType; +import org.opensearch.core.common.bytes.BytesArray; +import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.core.xcontent.XContentParser; +import org.opensearch.test.OpenSearchTestCase; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class JobDetailsTests extends OpenSearchTestCase { + + private JobDetails jobDetails; + + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + + @Before + public void setUp() throws Exception { + super.setUp(); + jobDetails = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + + } + + public void testConstructor() { + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + assertEquals(jobIndex, jobDetails.getJobIndex()); + assertEquals(jobType, jobDetails.getJobType()); + assertEquals(jobParameterAction, jobDetails.getJobParameterAction()); + assertEquals(jobRunnerAction, jobDetails.getJobRunnerAction()); + assertEquals(extensionUniqueId, jobDetails.getExtensionUniqueId()); + } + + public void testCopyConstructor() { + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + + JobDetails originalJobDetails = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + JobDetails copiedJobDetails = new JobDetails(originalJobDetails); + + assertEquals(originalJobDetails, copiedJobDetails); + } + + public void testSetters() { + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + + jobDetails.setJobIndex(jobIndex); + jobDetails.setJobType(jobType); + jobDetails.setJobParameterAction(jobParameterAction); + jobDetails.setJobRunnerAction(jobRunnerAction); + jobDetails.setExtensionUniqueId(extensionUniqueId); + + assertEquals(jobIndex, jobDetails.getJobIndex()); + assertEquals(jobType, jobDetails.getJobType()); + assertEquals(jobParameterAction, jobDetails.getJobParameterAction()); + assertEquals(jobRunnerAction, jobDetails.getJobRunnerAction()); + assertEquals(extensionUniqueId, jobDetails.getExtensionUniqueId()); + } + + public void testToXContent() throws IOException { + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + + JobDetails jobDetails = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + + XContentBuilder builder = XContentFactory.jsonBuilder(); + XContentBuilder xContentBuilder = jobDetails.toXContent(builder, null); + + String expectedJson = + "{\"job_index\":\"test_index\",\"job_type\":\"test_type\",\"job_parser_action\":\"test_parameter_action\",\"job_runner_action\":\"test_runner_action\",\"extension_unique_id\":\"test_extension_id\"}"; + assertEquals(expectedJson, xContentBuilder.toString()); + } + + public void testParseWithNullValues() throws IOException { + String json = + "{\"job_index\":null,\"job_type\":null,\"job_parser_action\":null,\"job_runner_action\":null,\"extension_unique_id\":null}"; + + XContentParser parser = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, null, new BytesArray(json.getBytes(StandardCharsets.UTF_8)).array()); + parser.nextToken(); // Advance to the START_OBJECT token + + JobDetails jobDetails = null; + try { + jobDetails = JobDetails.parse(parser); + } catch (IllegalStateException e) { + // Handle the "Can't get text on a VALUE_NULL" exception + if (e.getMessage().contains("Can't get text on a VALUE_NULL")) { + // Ignore the exception and set all fields to null + jobDetails = new JobDetails(null, null, null, null, null); + } else { + throw e; + } + } + + assertNull(jobDetails.getJobIndex()); + assertNull(jobDetails.getJobType()); + assertNull(jobDetails.getJobParameterAction()); + assertNull(jobDetails.getJobRunnerAction()); + assertNull(jobDetails.getExtensionUniqueId()); + } + + public void testEquals() { + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + + JobDetails jobDetails1 = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + JobDetails jobDetails2 = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + JobDetails jobDetails3 = new JobDetails(null, null, null, null, null); + + assertEquals(jobDetails1, jobDetails2); + assertNotNull(jobDetails1); + assertNotNull(jobDetails2); + assertNotNull(jobDetails3); + } + + public void testHashCode() { + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + + JobDetails jobDetails1 = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + JobDetails jobDetails2 = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + + assertEquals(jobDetails1.hashCode(), jobDetails2.hashCode()); + } + + public void testToString() { + String jobIndex = "test_index"; + String jobType = "test_type"; + String jobParameterAction = "test_parameter_action"; + String jobRunnerAction = "test_runner_action"; + String extensionUniqueId = "test_extension_id"; + + JobDetails jobDetails = new JobDetails(jobIndex, jobType, jobParameterAction, jobRunnerAction, extensionUniqueId); + + String expectedString = + "JobDetails{jobIndex='test_index', jobType='test_type', jobParameterAction='test_parameter_action', jobRunnerAction='test_runner_action', extensionUniqueId='test_extension_id'}"; + assertEquals(expectedString, jobDetails.toString()); + } +} diff --git a/src/test/java/org/opensearch/jobscheduler/utils/JobDetailsServiceIT.java b/src/test/java/org/opensearch/jobscheduler/utils/JobDetailsServiceIT.java index caa41649..a8287be4 100644 --- a/src/test/java/org/opensearch/jobscheduler/utils/JobDetailsServiceIT.java +++ b/src/test/java/org/opensearch/jobscheduler/utils/JobDetailsServiceIT.java @@ -9,6 +9,7 @@ package org.opensearch.jobscheduler.utils; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -371,7 +372,7 @@ public void testJobParameterExtensionJobActionRequest() throws IOException { String content = "{\"test_field\":\"test\"}"; JobDocVersion jobDocVersion = new JobDocVersion(1L, 1L, 1L); XContentParser parser = XContentType.JSON.xContent() - .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, content.getBytes()); + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, content.getBytes(StandardCharsets.UTF_8)); // Create JobParameterRequest JobParameterRequest jobParamRequest = new JobParameterRequest("placeholder", parser, "id", jobDocVersion);