diff --git a/.gitignore b/.gitignore index 4a93177f0..960e65c8d 100755 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,7 @@ tank_vmManager/settings.xml tank.mwb agent/http_client_3/settings.xml agent/http_client_4/settings.xml -agent/ok_http_client/settings.xml +agent/http_client_jdk/settings.xml # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/agent/agent_common/src/main/java/com/intuit/tank/http/BaseResponse.java b/agent/agent_common/src/main/java/com/intuit/tank/http/BaseResponse.java index 786e930ae..ea11fb8af 100644 --- a/agent/agent_common/src/main/java/com/intuit/tank/http/BaseResponse.java +++ b/agent/agent_common/src/main/java/com/intuit/tank/http/BaseResponse.java @@ -74,11 +74,22 @@ public String getLogMsg() { } this.responseLogMsg = sb.toString(); } catch (Exception ex) { - LOG.error("Error processing response: " + ex.getMessage(), ex); + LOG.error("Error processing response: {}", ex.getMessage(), ex); } return responseLogMsg; } + public String convertToCSV() { + StringBuilder sb = new StringBuilder(); + sb.append(this.httpCode).append(","); + sb.append(this.rspMessage).append(","); + sb.append(responseTime).append(","); + sb.append(getResponseSize()).append(","); + headers.forEach((key, value) -> sb.append(key).append(" = ").append(value.replace(",", "")).append(",")); + cookies.forEach((key, value) -> sb.append(key).append(" = ").append(value).append(",")); + return sb.toString(); + } + /** * Common codes are 200 OK, 202 accepted, 204 no content, 400 bad request, * 404 not found, 500 internal server error, 503 Service Unavailable diff --git a/agent/agent_startup_pkg/tank_agent/startAgent.sh b/agent/agent_startup_pkg/tank_agent/startAgent.sh index 3b799d01a..be2a8aca0 100755 --- a/agent/agent_startup_pkg/tank_agent/startAgent.sh +++ b/agent/agent_startup_pkg/tank_agent/startAgent.sh @@ -1,4 +1,4 @@ #!/bin/sh vm_arguments="-Dnetworkaddress.cache.ttl=5 -Dnetworkaddress.cache.negative.ttl=0"; -java -cp apiharness-1.0-all.jar $2 $vm_arguments com.intuit.tank.harness.APITestHarness $1 +java -cp apiharness-1.0-all.jar "${@:2}" $vm_arguments com.intuit.tank.harness.APITestHarness $1 echo DONE diff --git a/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java b/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java index 838e18cfa..5196e9bd9 100644 --- a/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java +++ b/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java @@ -95,6 +95,7 @@ public Object createHttpClient() { UserTokenHandler userTokenHandler = (httpContext) -> httpContext.getAttribute(HttpClientContext.USER_TOKEN); // default this implementation will create no more than than 2 concurrent connections per given route and no more 20 connections in total return HttpClients.custom() + .setConnectionManagerShared(true) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .setUserTokenHandler(userTokenHandler) .evictIdleConnections(1L, TimeUnit.MINUTES) diff --git a/api/src/main/resources/settings.xml b/api/src/main/resources/settings.xml index 87adc28c1..d1459f751 100644 --- a/api/src/main/resources/settings.xml +++ b/api/src/main/resources/settings.xml @@ -212,11 +212,11 @@ - - - - - + + + + + diff --git a/api/src/test/resources/settings.xml b/api/src/test/resources/settings.xml index fdcba513c..1c0df9472 100644 --- a/api/src/test/resources/settings.xml +++ b/api/src/test/resources/settings.xml @@ -212,11 +212,11 @@ - - - - - + + + + + diff --git a/assets/settings-all-in-one.xml b/assets/settings-all-in-one.xml index 15d8bd18f..e0fa37a74 100644 --- a/assets/settings-all-in-one.xml +++ b/assets/settings-all-in-one.xml @@ -163,11 +163,11 @@ - - - - - + + + + + diff --git a/aws-config/tank_agent.yml b/aws-config/tank_agent.yml index beede6806..735ce1db6 100644 --- a/aws-config/tank_agent.yml +++ b/aws-config/tank_agent.yml @@ -11,7 +11,7 @@ Parameters: InstanceType: Description: Amazon EC2 instance type Type: 'String' - Default: 'c5.large' + Default: 'm8g.large' KeyName: Type: 'AWS::EC2::KeyPair::KeyName' Description: Amazon EC2 Key Pair diff --git a/pom.xml b/pom.xml index 0ea2337ac..eb8ab0022 100644 --- a/pom.xml +++ b/pom.xml @@ -30,10 +30,10 @@ self_signed_tank.p12 6.5.1.Final - 2.25.56 - 2.15.3 + 2.29.35 + 2.18.2 - 11.0.1 + 11.0.2 5.1.3.Final 4.1.0 diff --git a/proxy-parent/owasp-proxy/pom.xml b/proxy-parent/owasp-proxy/pom.xml index 7d6fbd1e3..e3e90dafd 100755 --- a/proxy-parent/owasp-proxy/pom.xml +++ b/proxy-parent/owasp-proxy/pom.xml @@ -32,14 +32,14 @@ org.bouncycastle - bcprov-jdk15on - 1.47 + bcprov-jdk18on + 1.79 org.bouncycastle - bcpkix-jdk15on - 1.47 + bcpkix-jdk18on + 1.79 org.apache.httpcomponents @@ -48,7 +48,7 @@ org.springframework spring-jdbc - 2.5.6 + 6.2.0 compile diff --git a/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/http/dao/JdbcMessageDAO.java b/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/http/dao/JdbcMessageDAO.java index 024f3b981..74fd79ef8 100644 --- a/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/http/dao/JdbcMessageDAO.java +++ b/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/http/dao/JdbcMessageDAO.java @@ -42,10 +42,10 @@ import org.springframework.dao.DataAccessException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; -import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; @@ -66,11 +66,11 @@ public class JdbcMessageDAO extends NamedParameterJdbcDaoSupport implements private static final String RESPONSE_HEADER_TIME = "headerTime"; private static final String RESPONSE_CONTENT_TIME = "contentTime"; - private static final ParameterizedRowMapper REQUEST_MAPPER = new RequestMapper(); - private static final ParameterizedRowMapper RESPONSE_MAPPER = new ResponseMapper(); - private static final ParameterizedRowMapper CONTENT_MAPPER = new ContentMapper(); - private static final ParameterizedRowMapper ID_MAPPER = new IdMapper(); - private static final ParameterizedRowMapper CONVERSATION_MAPPER = new ConversationMapper(); + private static final RowMapper REQUEST_MAPPER = new RequestMapper(); + private static final RowMapper RESPONSE_MAPPER = new ResponseMapper(); + private static final RowMapper CONTENT_MAPPER = new ContentMapper(); + private static final RowMapper ID_MAPPER = new IdMapper(); + private static final RowMapper CONVERSATION_MAPPER = new ConversationMapper(); private final static String INSERT_CONTENT = "INSERT INTO contents (content, size) VALUES (:content, :size)"; @@ -188,9 +188,8 @@ public Collection listConversationsSince(int id) MapSqlParameterSource params = new MapSqlParameterSource(); try { params.addValue(ID, id, Types.INTEGER); - SimpleJdbcTemplate template = new SimpleJdbcTemplate( - getNamedParameterJdbcTemplate()); - return template.query(SELECT_CONVERSATIONS, ID_MAPPER, params); + NamedParameterJdbcTemplate template = getNamedParameterJdbcTemplate(); + return template.query(SELECT_CONVERSATIONS, params, ID_MAPPER); } catch (EmptyResultDataAccessException erdae) { return Collections.emptyList(); } @@ -205,9 +204,8 @@ public int getMessageContentId(int headerId) throws DataAccessException { try { MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue(ID, headerId, Types.INTEGER); - SimpleJdbcTemplate template = new SimpleJdbcTemplate( - getNamedParameterJdbcTemplate()); - return template.queryForInt(SELECT_CONTENT_ID, params); + NamedParameterJdbcTemplate template = getNamedParameterJdbcTemplate(); + return template.queryForObject(SELECT_CONTENT_ID, params, Integer.class); } catch (EmptyResultDataAccessException erdae) { return -1; } @@ -222,9 +220,8 @@ public int getMessageContentSize(int id) throws DataAccessException { try { MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue(ID, id, Types.INTEGER); - SimpleJdbcTemplate template = new SimpleJdbcTemplate( - getNamedParameterJdbcTemplate()); - return template.queryForInt(SELECT_CONTENT_SIZE, params); + NamedParameterJdbcTemplate template = getNamedParameterJdbcTemplate(); + return template.queryForObject(SELECT_CONTENT_SIZE, params, Integer.class); } catch (EmptyResultDataAccessException erdae) { return -1; } @@ -239,10 +236,8 @@ public Conversation getConversation(int id) throws DataAccessException { try { MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue(ID, id, Types.INTEGER); - SimpleJdbcTemplate template = new SimpleJdbcTemplate( - getNamedParameterJdbcTemplate()); - return template.queryForObject(SELECT_SUMMARY, CONVERSATION_MAPPER, - params); + NamedParameterJdbcTemplate template = getNamedParameterJdbcTemplate(); + return template.queryForObject(SELECT_SUMMARY, params, CONVERSATION_MAPPER); } catch (EmptyResultDataAccessException erdae) { return null; } @@ -286,10 +281,8 @@ public byte[] loadMessageContent(int id) throws DataAccessException { try { MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue(ID, id, Types.INTEGER); - SimpleJdbcTemplate template = new SimpleJdbcTemplate( - getNamedParameterJdbcTemplate()); - return template.queryForObject(SELECT_CONTENT, CONTENT_MAPPER, - params); + NamedParameterJdbcTemplate template = getNamedParameterJdbcTemplate(); + return template.queryForObject(SELECT_CONTENT, params, CONTENT_MAPPER); } catch (EmptyResultDataAccessException erdae) { return null; } @@ -319,10 +312,8 @@ public RequestHeader loadRequestHeader(int id) throws DataAccessException { MapSqlParameterSource params = new MapSqlParameterSource(); try { params.addValue(ID, id, Types.INTEGER); - SimpleJdbcTemplate template = new SimpleJdbcTemplate( - getNamedParameterJdbcTemplate()); - return template.queryForObject(SELECT_REQUEST, REQUEST_MAPPER, - params); + NamedParameterJdbcTemplate template = getNamedParameterJdbcTemplate(); + return template.queryForObject(SELECT_REQUEST, params, REQUEST_MAPPER); } catch (EmptyResultDataAccessException erdae) { return null; } @@ -354,10 +345,8 @@ public MutableResponseHeader loadResponseHeader(int id) try { MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue(ID, id, Types.INTEGER); - SimpleJdbcTemplate template = new SimpleJdbcTemplate( - getNamedParameterJdbcTemplate()); - return template.queryForObject(SELECT_RESPONSE, RESPONSE_MAPPER, - params); + NamedParameterJdbcTemplate template = getNamedParameterJdbcTemplate(); + return template.queryForObject(SELECT_RESPONSE, params, RESPONSE_MAPPER); } catch (EmptyResultDataAccessException erdae) { return null; } @@ -478,7 +467,7 @@ private void saveMessageHeader(MutableMessageHeader header, int contentId) { } private static class RequestMapper implements - ParameterizedRowMapper { + RowMapper { public MutableBufferedRequest mapRow(ResultSet rs, int rowNum) throws SQLException { @@ -504,7 +493,7 @@ public MutableBufferedRequest mapRow(ResultSet rs, int rowNum) } private static class ResponseMapper implements - ParameterizedRowMapper { + RowMapper { public MutableBufferedResponse mapRow(ResultSet rs, int rowNum) throws SQLException { @@ -529,14 +518,14 @@ public MutableBufferedResponse mapRow(ResultSet rs, int rowNum) } private static class ContentMapper implements - ParameterizedRowMapper { + RowMapper { public byte[] mapRow(ResultSet rs, int rowNum) throws SQLException { return rs.getBytes(CONTENT); } } - private static class IdMapper implements ParameterizedRowMapper { + private static class IdMapper implements RowMapper { public Integer mapRow(ResultSet rs, int rowNum) throws SQLException { return Integer.valueOf(rs.getInt(ID)); @@ -544,7 +533,7 @@ public Integer mapRow(ResultSet rs, int rowNum) throws SQLException { } private static class ConversationMapper implements - ParameterizedRowMapper { + RowMapper { public Conversation mapRow(ResultSet rs, int rowNum) throws SQLException { diff --git a/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/util/BouncyCastleCertificateUtils.java b/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/util/BouncyCastleCertificateUtils.java index 4cd25d7da..5aa559ad4 100644 --- a/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/util/BouncyCastleCertificateUtils.java +++ b/proxy-parent/owasp-proxy/src/main/java/org/owasp/proxy/util/BouncyCastleCertificateUtils.java @@ -34,14 +34,10 @@ import javax.security.auth.x500.X500Principal; -import org.bouncycastle.asn1.x509.BasicConstraints; -import org.bouncycastle.asn1.x509.ExtendedKeyUsage; -import org.bouncycastle.asn1.x509.KeyPurposeId; -import org.bouncycastle.asn1.x509.X509Extensions; +import org.bouncycastle.asn1.x509.*; import org.bouncycastle.jce.X509KeyUsage; import org.bouncycastle.x509.X509V3CertificateGenerator; import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure; -import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure; @SuppressWarnings("deprecation") public class BouncyCastleCertificateUtils { @@ -116,7 +112,7 @@ private static void addCertificateExtensions(PublicKey pubKey, // new SubjectKeyIdentifierExtension(new KeyIdentifier(pubKey) // .getIdentifier())); certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, - new SubjectKeyIdentifierStructure(pubKey)); + SubjectKeyIdentifier.getInstance(pubKey)); // // ext.set(AuthorityKeyIdentifierExtension.NAME, // new AuthorityKeyIdentifierExtension( diff --git a/rest-mvc/impl/src/main/java/com/intuit/tank/rest/mvc/rest/controllers/JobController.java b/rest-mvc/impl/src/main/java/com/intuit/tank/rest/mvc/rest/controllers/JobController.java index 011791b41..eb361e860 100644 --- a/rest-mvc/impl/src/main/java/com/intuit/tank/rest/mvc/rest/controllers/JobController.java +++ b/rest-mvc/impl/src/main/java/com/intuit/tank/rest/mvc/rest/controllers/JobController.java @@ -89,7 +89,7 @@ public ResponseEntity getJobsByProject(@PathVariable @Parameter(de " - passing only projectName creates jobs named: '{projectName}_{total_users}\\_users\\_{timestamp}' \n\n" + " - rampTime and simulationTime are accepted as time strings i.e 60s, 12m, 24h \n\n" + " - stopBehavior is matched against accepted values ( END_OF_STEP, END_OF_SCRIPT, END_OF_SCRIPT_GROUP, END_OF_TEST ) \n\n" + - " - vmInstance matches against AWS EC2 Instance Types i.e c5.large, c5.xlarge, etc \n\n"+ + " - vmInstance matches against AWS EC2 Instance Types i.e m8g.large, m8g.xlarge, etc \n\n"+ " - workloadType can be set to increasing (linear workload) or standard (nonlinear workload) \n\n"+ " - targetRampRate, targetRatePerAgent, and jobRegions.percentage fields apply to standard workloadType jobs (nonlinear) \n\n"+ " - projectId, userIntervalIncrement and numUsersPerAgent are accepted as integers \n\n" + diff --git a/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/ActionComponents.java b/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/ActionComponents.java index 2f8a9f2e8..23ec6013b 100644 --- a/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/ActionComponents.java +++ b/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/ActionComponents.java @@ -185,6 +185,8 @@ private void createToolBar(JComboBox testPlanChooser, JComboBox step.getResponse() != null) + .map(step -> step.getRequest().getRequestUrl() + "," + step.getResponse().convertToCSV()) + .forEach(pw::println); + } catch ( FileNotFoundException e) { + LOG.error("Error exporting CSV: {}", String.valueOf(e)); + } + } + } diff --git a/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/PanelBuilder.java b/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/PanelBuilder.java index a62692e25..17ead38f8 100644 --- a/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/PanelBuilder.java +++ b/tools/agent_debugger/src/main/java/com/intuit/tank/tools/debugger/PanelBuilder.java @@ -184,7 +184,7 @@ static Component createContentPanel(final AgentDebuggerFrame frame) { public void mousePressed(MouseEvent e) { scriptEditorTA.grabFocus(); try { - int offs = scriptEditorTA.viewToModel(e.getPoint()); + int offs = scriptEditorTA.viewToModel2D(e.getPoint()); if (offs > -1) { int line = scriptEditorTA.getLineOfOffset(offs); if (frame.getSteps().size() > line) { diff --git a/tools/agent_debugger/src/main/resources/gfx/16/database_table.png b/tools/agent_debugger/src/main/resources/gfx/16/database_table.png new file mode 100644 index 000000000..03c52ee23 Binary files /dev/null and b/tools/agent_debugger/src/main/resources/gfx/16/database_table.png differ diff --git a/web/web_support/src/main/java/com/intuit/tank/project/JobMaker.java b/web/web_support/src/main/java/com/intuit/tank/project/JobMaker.java index de4bfe26e..f266cef82 100644 --- a/web/web_support/src/main/java/com/intuit/tank/project/JobMaker.java +++ b/web/web_support/src/main/java/com/intuit/tank/project/JobMaker.java @@ -47,7 +47,6 @@ import com.intuit.tank.util.TestParameterContainer; import com.intuit.tank.vm.api.enumerated.JobLifecycleEvent; import com.intuit.tank.vm.api.enumerated.TerminationPolicy; -import com.intuit.tank.vm.common.util.MethodTimer; import com.intuit.tank.vm.event.JobEvent; import com.intuit.tank.vm.settings.TankConfig; import com.intuit.tank.vm.settings.VmInstanceType; @@ -81,7 +80,7 @@ public class JobMaker implements Serializable { @Inject private UsersAndTimes usersAndTimes; - private JobInstance proposedJobInstance; + protected JobInstance proposedJobInstance; private String jobDetails; @@ -358,21 +357,18 @@ public void createJobInstance() { proposedJobInstance.getJobRegionVersions().addAll(getVersions(jobRegionDao, jobRegions)); JobValidator validator = new JobValidator(workload.getTestPlans(), proposedJobInstance.getVariables(), false); - long maxDuration = 0; - for (TestPlan plan : workload.getTestPlans()) { - maxDuration = Math.max(validator.getDurationMs(plan.getName()), maxDuration); - } + long maxDuration = workload.getTestPlans().stream() + .mapToLong(plan -> validator.getDurationMs(plan.getName())) + .max().orElse(0); TestParameterContainer times = TestParamUtil.evaluateTestTimes(maxDuration, projectBean .getJobConfiguration().getRampTimeExpression(), projectBean.getJobConfiguration() .getSimulationTimeExpression()); proposedJobInstance.setExecutionTime(maxDuration); proposedJobInstance.setRampTime(times.getRampTime()); proposedJobInstance.setSimulationTime(times.getSimulationTime()); - int totalVirtualUsers = 0; - for (JobRegion region : jobRegions) { - totalVirtualUsers += TestParamUtil.evaluateExpression(region.getUsers(), maxDuration, - times.getSimulationTime(), times.getRampTime()); - } + int totalVirtualUsers = jobRegions.stream() + .mapToInt(region -> (int) TestParamUtil.evaluateExpression(region.getUsers(), maxDuration, + times.getSimulationTime(), times.getRampTime())).sum(); proposedJobInstance.setTotalVirtualUsers(totalVirtualUsers); } } @@ -382,7 +378,7 @@ public String getJobDetails() { try { jobDetails = createJobDetails(); } catch (Exception e) { - LOG.error("Error building jobDetails: " + e, e); + LOG.error("Error building jobDetails: {}", e, e); return "Error building jobDetails: "; } } @@ -401,27 +397,19 @@ private String createJobDetails() { public void addJobToQueue() { if (proposedJobInstance != null) { - MethodTimer mt = new MethodTimer(LOG, this.getClass(), "addJobToQueue"); JobQueueDao jobQueueDao = new JobQueueDao(); Workload workload = projectBean.getWorkload(); JobQueue queue = jobQueueDao.findOrCreateForProjectId(projectBean.getProject().getId()); proposedJobInstance.setJobDetails(jobDetails); - mt.markAndLog("Create Job Details"); queue.addJob(proposedJobInstance); - mt.markAndLog("Add job to queue"); jobQueueDao.saveOrUpdate(queue); - mt.markAndLog("save queue"); storeScript(Integer.toString(proposedJobInstance.getId()), workload, proposedJobInstance); - mt.markAndLog("store script"); messages.info("Job has been submitted successfully"); jobQueueEvent.fire(queue); - mt.markAndLog("fire queue event"); jobEventProducer.fire(new JobEvent(Integer.toString(proposedJobInstance.getId()), "", JobLifecycleEvent.QUEUE_ADD)); - mt.markAndLog("fire job event QUEUE_ADD"); setName(null); proposedJobInstance = null; - mt.endAndLog(); } } @@ -458,10 +446,8 @@ public boolean isValid() { return false; } if(proposedJobInstance.getIncrementStrategy().equals(IncrementStrategy.standard)){ - int regionPercentage = 0; - for (JobRegion r : projectBean.getWorkload().getJobConfiguration().getJobRegions()) { - regionPercentage += Integer.parseInt(r.getPercentage()); - } + int regionPercentage = projectBean.getWorkload().getJobConfiguration().getJobRegions().stream() + .mapToInt(r -> Integer.parseInt(r.getPercentage())).sum(); if (regionPercentage != 100) { return false; } @@ -470,16 +456,9 @@ public boolean isValid() { } private boolean hasScripts() { - Workload workload = projectBean.getWorkload(); - workload.getTestPlans(); - for (TestPlan plan : workload.getTestPlans()) { - for (ScriptGroup group : plan.getScriptGroups()) { - if (!group.getScriptGroupSteps().isEmpty()) { - return true; - } - } - } - return false; + return projectBean.getWorkload().getTestPlans().stream() + .flatMap(testPlan -> testPlan.getScriptGroups().stream()) + .anyMatch(scriptGroup -> !scriptGroup.getScriptGroupSteps().isEmpty()); } /** diff --git a/web/web_support/src/test/java/com/intuit/tank/project/JobDetailFormatterTest.java b/web/web_support/src/test/java/com/intuit/tank/project/JobDetailFormatterTest.java index 078ec0634..6513c8f93 100644 --- a/web/web_support/src/test/java/com/intuit/tank/project/JobDetailFormatterTest.java +++ b/web/web_support/src/test/java/com/intuit/tank/project/JobDetailFormatterTest.java @@ -83,8 +83,8 @@ public void getSimulationTime() { @Test public void getVmDetails() { - String vmDetails = JobDetailFormatter.getVmDetails(new TankConfig(), "c5.xlarge"); - assertEquals("c5.xlarge (cpus=4 ecus=16 memory=8.0 cost=$0.17 per hour)", vmDetails); + String vmDetails = JobDetailFormatter.getVmDetails(new TankConfig(), "m8g.xlarge"); + assertEquals("m8g.xlarge (cpus=4 ecus=16 memory=16.0 cost=$0.1795 per hour)", vmDetails); } /** diff --git a/web/web_support/src/test/java/com/intuit/tank/project/JobMakerTest.java b/web/web_support/src/test/java/com/intuit/tank/project/JobMakerTest.java new file mode 100644 index 000000000..1ae4e75af --- /dev/null +++ b/web/web_support/src/test/java/com/intuit/tank/project/JobMakerTest.java @@ -0,0 +1,181 @@ +package com.intuit.tank.project; + +import com.intuit.tank.PreferencesBean; +import com.intuit.tank.ProjectBean; +import com.intuit.tank.auth.TankSecurityContext; +import com.intuit.tank.util.Messages; +import com.intuit.tank.vm.api.enumerated.IncrementStrategy; +import com.intuit.tank.vm.api.enumerated.TerminationPolicy; +import com.intuit.tank.vm.event.JobEvent; +import jakarta.enterprise.context.ConversationScoped; +import jakarta.enterprise.event.Event; +import org.apache.commons.lang3.time.FastDateFormat; +import org.jboss.weld.junit5.auto.ActivateScopes; +import org.jboss.weld.junit5.auto.EnableAutoWeld; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.*; + +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; + +@EnableAutoWeld +@ActivateScopes(ConversationScoped.class) +public class JobMakerTest { + + @InjectMocks + private JobMaker jobMaker; + + @Mock + private Event jobQueueEvent; + + @Mock + private Event jobEventProducer; + + @Mock + private Messages messages; + + @Mock + private PreferencesBean preferences; + + @Mock + private UsersAndTimes usersAndTimes; + + @Mock + private TankSecurityContext securityContext; + + private AutoCloseable closeable; + + @BeforeEach + void initService() { + closeable = MockitoAnnotations.openMocks(this); + } + + @AfterEach + void closeService() throws Exception { + closeable.close(); + } + + @Test + public void testGetName() { + ProjectBean mockProjectBean = mock(ProjectBean.class); + JobConfiguration mockJobConfiguration = mock(JobConfiguration.class); + Mockito.when(mockJobConfiguration.getIncrementStrategy()).thenReturn(IncrementStrategy.increasing); + Mockito.when(mockJobConfiguration.getWorkload()).thenReturn(mock(Workload.class)); + Mockito.when(mockProjectBean.getJobConfiguration()).thenReturn(mockJobConfiguration); + Mockito.when(usersAndTimes.getTotalUsers()).thenReturn(10); + Mockito.when(preferences.getTimestampFormat()).thenReturn(FastDateFormat.getInstance("yyyy.MM.dd-HH:mm:ss.S z")); + jobMaker.init(mockProjectBean); + assertTrue(jobMaker.getName().contains("_10_users_")); + + Mockito.when(mockJobConfiguration.getIncrementStrategy()).thenReturn(IncrementStrategy.standard); + jobMaker.init(mockProjectBean); + assertTrue(jobMaker.getName().contains("_nonlinear_")); + } + + @Test + public void testSetVmInstanceType() { + jobMaker.setVmInstanceType(""); + + ProjectBean projectBean = mock(ProjectBean.class); + JobConfiguration mockJobConfiguration = mock(JobConfiguration.class); + Mockito.when(projectBean.getJobConfiguration()).thenReturn(mockJobConfiguration); + jobMaker.init(projectBean); + jobMaker.setVmInstanceType("m8g.2xlarge"); + } + + @Test void testTargetRatePerAgent() { + ProjectBean mockProjectBean = mock(ProjectBean.class); + JobConfiguration jobConfiguration = new JobConfiguration(); + Mockito.when(mockProjectBean.getJobConfiguration()).thenReturn(jobConfiguration); + jobMaker.init(mockProjectBean); + jobMaker.setTargetRatePerAgent(10.0); + assertEquals(10.0, jobMaker.getTargetRatePerAgent()); + } + + @Test + public void testCreateJobInstance() { + ProjectBean mockProjectBean = mock(ProjectBean.class); + JobConfiguration mockJobConfiguration = mock(JobConfiguration.class); + Workload mockWorkload = mock(Workload.class); + Mockito.when(mockWorkload.getJobConfiguration()).thenReturn(mockJobConfiguration); + Mockito.when(mockJobConfiguration.getIncrementStrategy()).thenReturn(IncrementStrategy.increasing); + Mockito.when(mockJobConfiguration.getWorkload()).thenReturn(mockWorkload); + Mockito.when(mockJobConfiguration.getDataFileIds()).thenReturn(Set.of(1)); + Mockito.when(mockJobConfiguration.getNotifications()).thenReturn(Set.of(new JobNotification())); + Mockito.when(mockProjectBean.getWorkload()).thenReturn(mockWorkload); + Mockito.when(mockProjectBean.getJobConfiguration()).thenReturn(mockJobConfiguration); + Mockito.when(mockProjectBean.doSave()).thenReturn(Boolean.TRUE); + jobMaker.init(mockProjectBean); + Mockito.when(preferences.getTimestampFormat()).thenReturn(FastDateFormat.getInstance("yyyy.MM.dd-HH:mm:ss.S z")); + Mockito.when(securityContext.getCallerPrincipal()).thenReturn(() -> "TEST_USER"); + try (MockedStatic mockedStatic = Mockito.mockStatic(JobDetailFormatter.class)) { + mockedStatic.when(() -> JobDetailFormatter.createJobDetails(any(), any(), any())).thenReturn("TEST_JOB_DETAILS"); + jobMaker.createJobInstance(); + assertEquals("TEST_JOB_DETAILS", jobMaker.getJobDetails()); + } + } + + @Test + public void testAddJobToQueue() { + jobMaker.proposedJobInstance = new JobInstance(); + ProjectBean mockProjectBean = mock(ProjectBean.class); + JobConfiguration mockJobConfiguration = mock(JobConfiguration.class); + Workload mockWorkload = mock(Workload.class); + Project mockProject = mock(Project.class); + Mockito.when(mockProjectBean.getProject()).thenReturn(mockProject); + Mockito.when(mockJobConfiguration.getIncrementStrategy()).thenReturn(IncrementStrategy.increasing); + Mockito.when(mockJobConfiguration.getWorkload()).thenReturn(mockWorkload); + Mockito.when(mockProjectBean.getJobConfiguration()).thenReturn(mockJobConfiguration); + Mockito.when(mockProjectBean.getWorkload()).thenReturn(mockWorkload); + Mockito.when(mockWorkload.getProject()).thenReturn(mockProject); + Mockito.when(usersAndTimes.getTotalUsers()).thenReturn(10); + Mockito.when(preferences.getTimestampFormat()).thenReturn(FastDateFormat.getInstance("yyyy.MM.dd-HH:mm:ss.S z")); + jobMaker.init(mockProjectBean); + jobMaker.addJobToQueue(); + assertNull(jobMaker.getProposedJobInstance()); + } + + @Test + public void testIsValid() { + jobMaker.proposedJobInstance = null; + assertFalse(jobMaker.isValid()); + + jobMaker.proposedJobInstance = new JobInstance(); + assertFalse(jobMaker.isValid()); + + jobMaker.setName("TEST"); + jobMaker.getProposedJobInstance().setIncrementStrategy(IncrementStrategy.increasing); + assertFalse(jobMaker.isValid()); + + jobMaker.getProposedJobInstance().setIncrementStrategy(IncrementStrategy.standard); + jobMaker.getProposedJobInstance().setTerminationPolicy(TerminationPolicy.time); + jobMaker.getProposedJobInstance().setSimulationTime(0); + assertFalse(jobMaker.isValid()); + + jobMaker.getProposedJobInstance().setSimulationTime(10); + ProjectBean mockProjectBean = mock(ProjectBean.class); + Workload mockWorkload = mock(Workload.class); + Mockito.when(mockProjectBean.getWorkload()).thenReturn(mockWorkload); + jobMaker.init(mockProjectBean); + assertFalse(jobMaker.isValid()); + + TestPlan testPlan = TestPlan.builder().build(); + ScriptGroup scriptGroup = ScriptGroup.builder().build(); + scriptGroup.addScriptGroupStep(ScriptGroupStep.builder().build()); + testPlan.addScriptGroup(scriptGroup); + Mockito.when(mockWorkload.getTestPlans()).thenReturn(List.of(testPlan)); + JobConfiguration mockJobConfiguration = mock(JobConfiguration.class); + Mockito.when(mockWorkload.getJobConfiguration()).thenReturn(mockJobConfiguration); + assertFalse(jobMaker.isValid()); + + Mockito.when(mockJobConfiguration.getJobRegions()).thenReturn( + Set.of(JobRegion.builder().percentage("100").build())); + assertTrue(jobMaker.isValid()); + } +}