public class FindMultipleMatchesTest { private static final Logger log = Logger.getLogger(FindMultipleMatchesTest.class); @Test public void findsMultipleGroups() { Pattern pattern = compile("\\w* "); Matcher matcher = pattern.matcher("this is a sentance"); log.info("GroupCount: " + matcher.groupCount()); while (matcher.find()) { log.info("Found group : [" + matcher.group().trim() + "]"); } } @Test public void findStructuredGroups() { Pattern pattern = compile("\\{\\w*\\}"); Matcher matcher = pattern.matcher("/{parameter1}/some/path/{parameter2}/end"); while (matcher.find()) { log.info("Found parameter: [" + matcher.group().replaceAll("\\{|\\}", "") + "]"); } String output = matcher.replaceAll("(.*)"); log.info("Replaced output: [" + output + "]"); } @Test public void findStructuredGroupsWithParenthesis() { Pattern pattern = compile("\\([^\\)]*\\)"); Matcher matcher = pattern.matcher("Some sentance (parameter 1d) /some/path/ (parameter 2 ) /end"); while (matcher.find()) { log.info("Found parameter: [" + matcher.group().replaceAll("\\(|\\)", "") + "]"); } String output = matcher.replaceAll("(.*)"); log.info("Replaced output: [" + output + "]"); } }
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( locations = { "classpath:WEB-INF/applicationContext-global.xml", "classpath:WEB-INF/applicationContext-dataLocalAccess.xml", "classpath:WEB-INF/applicationContext-acegi-security.xml" }) public class PipelineConfigServicePerformanceTest { private static String consoleAppenderForPerformanceTest; private static String rollingFileAppenderForPerformanceTest; static { new SystemEnvironment().setProperty(GoConstants.USE_COMPRESSED_JAVASCRIPT, "false"); Logger rootLogger = Logger.getRootLogger(); rootLogger.setLevel(Level.INFO); try { Filter filter = new Filter() { @Override public int decide(LoggingEvent loggingEvent) { return loggingEvent.getLoggerName().startsWith("com.thoughtworks.go.util.PerfTimer") || loggingEvent .getLoggerName() .startsWith( "com.thoughtworks.go.server.service.PipelineConfigServicePerformanceTest") ? 0 : -1; } }; ConsoleAppender consoleAppender = new ConsoleAppender(new PatternLayout("%d [%p|%c|%C{1}] %m%n")); consoleAppender.addFilter(filter); consoleAppender.setName(consoleAppenderForPerformanceTest); RollingFileAppender rollingFileAppender = new RollingFileAppender( new PatternLayout("%d [%p|%c|%C{1}] %m%n"), "/tmp/config-save-perf.log", false); rollingFileAppender.addFilter(filter); rollingFileAppender.setName(rollingFileAppenderForPerformanceTest); rootLogger.addAppender(rollingFileAppender); rootLogger.addAppender(consoleAppender); } catch (IOException e) { e.printStackTrace(); } } @Autowired private PipelineConfigService pipelineConfigService; @Autowired private GoConfigService goConfigService; @Autowired private GoConfigDao goConfigDao; @Autowired private DatabaseAccessHelper dbHelper; @Autowired private GoConfigMigration goConfigMigration; @Autowired private EntityHashingService entityHashingService; @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); private GoConfigFileHelper configHelper; private final int numberOfRequests = 100; private HttpLocalizedOperationResult result; private Username user; private static Logger LOGGER = Logger.getLogger(PipelineConfigServicePerformanceTest.class.getName()); @AfterClass public static void removeLogger() { LOGGER.removeAppender(consoleAppenderForPerformanceTest); LOGGER.removeAppender(rollingFileAppenderForPerformanceTest); } @Before public void setup() throws Exception { configHelper = new GoConfigFileHelper(); dbHelper.onSetUp(); configHelper.usingCruiseConfigDao(goConfigDao).initializeConfigFile(); configHelper.onSetUp(); goConfigService.forceNotifyListeners(); File dumpDir = tempFolder.newFolder("perf-pipelineapi-test"); FileUtil.deleteDirectoryNoisily(dumpDir); dumpDir.mkdirs(); result = new HttpLocalizedOperationResult(); user = new Username(new CaseInsensitiveString("admin")); consoleAppenderForPerformanceTest = "ConsoleAppenderForPerformanceTest"; rollingFileAppenderForPerformanceTest = "RollingFileAppenderForPerformanceTest"; } @After public void tearDown() throws Exception { configHelper.onTearDown(); dbHelper.onTearDown(); } @Test @Ignore public void performanceTestForUpdatePipeline() throws Exception { setupPipelines(numberOfRequests); final ConcurrentHashMap<String, Boolean> results = new ConcurrentHashMap<>(); run( new Runnable() { @Override public void run() { PipelineConfig pipelineConfig = goConfigService .getConfigForEditing() .pipelineConfigByName( new CaseInsensitiveString(Thread.currentThread().getName())); pipelineConfig.add( new StageConfig( new CaseInsensitiveString("additional_stage"), new JobConfigs(new JobConfig(new CaseInsensitiveString("addtn_job"))))); PerfTimer updateTimer = PerfTimer.start("Saving pipelineConfig : " + pipelineConfig.name()); pipelineConfigService.updatePipelineConfig( user, pipelineConfig, entityHashingService.md5ForEntity(pipelineConfig), result); updateTimer.stop(); results.put(Thread.currentThread().getName(), result.isSuccessful()); if (!result.isSuccessful()) { LOGGER.error(result.toString()); LOGGER.error( "Errors on pipeline" + Thread.currentThread().getName() + " are : " + ListUtil.join(getAllErrors(pipelineConfig))); } } }, numberOfRequests, results); } @Test @Ignore public void performanceTestForDeletePipeline() throws Exception { setupPipelines(numberOfRequests); final ConcurrentHashMap<String, Boolean> results = new ConcurrentHashMap<>(); run( new Runnable() { @Override public void run() { PipelineConfig pipelineConfig = goConfigService .getConfigForEditing() .pipelineConfigByName( new CaseInsensitiveString(Thread.currentThread().getName())); pipelineConfig.add( new StageConfig( new CaseInsensitiveString("additional_stage"), new JobConfigs(new JobConfig(new CaseInsensitiveString("addtn_job"))))); PerfTimer updateTimer = PerfTimer.start("Saving pipelineConfig : " + pipelineConfig.name()); pipelineConfigService.deletePipelineConfig(user, pipelineConfig, result); updateTimer.stop(); results.put(Thread.currentThread().getName(), result.isSuccessful()); if (!result.isSuccessful()) { LOGGER.error(result.toString()); LOGGER.error( "Errors on pipeline" + Thread.currentThread().getName() + " are : " + ListUtil.join(getAllErrors(pipelineConfig))); } } }, numberOfRequests, results); } @Test @Ignore public void performanceTestForCreatePipeline() throws Exception { setupPipelines(0); final ConcurrentHashMap<String, Boolean> results = new ConcurrentHashMap<>(); run( new Runnable() { @Override public void run() { JobConfig jobConfig = new JobConfig(new CaseInsensitiveString("job")); StageConfig stageConfig = new StageConfig(new CaseInsensitiveString("stage"), new JobConfigs(jobConfig)); PipelineConfig pipelineConfig = new PipelineConfig( new CaseInsensitiveString(Thread.currentThread().getName()), new MaterialConfigs(new GitMaterialConfig("FOO")), stageConfig); PerfTimer updateTimer = PerfTimer.start("Saving pipelineConfig : " + pipelineConfig.name()); pipelineConfigService.createPipelineConfig(user, pipelineConfig, result, "jumbo"); updateTimer.stop(); results.put(Thread.currentThread().getName(), result.isSuccessful()); if (!result.isSuccessful()) { LOGGER.error(result.toString()); LOGGER.error( "Errors on pipeline" + Thread.currentThread().getName() + " are : " + ListUtil.join(getAllErrors(pipelineConfig))); } } }, numberOfRequests, results); } private void run( Runnable runnable, int numberOfRequests, final ConcurrentHashMap<String, Boolean> results) throws InterruptedException { Boolean finalResult = true; LOGGER.info("Tests start now!"); final ArrayList<Thread> threads = new ArrayList<>(); for (int i = 0; i < numberOfRequests; i++) { Thread t = new Thread(runnable, "pipeline" + i); threads.add(t); } for (Thread t : threads) { Thread.sleep(1000 * (new Random().nextInt(3) + 1)); t.setUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { LOGGER.error("Exception " + e + " from thread " + t); results.put(t.getName(), false); } }); t.start(); } for (Thread t : threads) { int i = threads.indexOf(t); if (i == (numberOfRequests - 1)) { // takeHeapDump(dumpDir, i); } t.join(); } for (String threadId : results.keySet()) { finalResult = results.get(threadId) && finalResult; } assertThat(finalResult, is(true)); } private void takeHeapDump(File dumpDir, int i) { InMemoryStreamConsumer outputStreamConsumer = inMemoryConsumer(); CommandLine commandLine = CommandLine.createCommandLine("jmap") .withArgs( "-J-d64", String.format("-dump:format=b,file=%s/%s.hprof", dumpDir.getAbsoluteFile(), i), ManagementFactory.getRuntimeMXBean().getName().split("@")[0]); LOGGER.info(commandLine.describe()); int exitCode = commandLine.run(outputStreamConsumer, "thread" + i); LOGGER.info(outputStreamConsumer.getAllOutput()); assertThat(exitCode, is(0)); LOGGER.info(String.format("Heap dump available at %s", dumpDir.getAbsolutePath())); } private abstract static class ErrorCollectingHandler implements GoConfigGraphWalker.Handler { private final List<ConfigErrors> allErrors; public ErrorCollectingHandler(List<ConfigErrors> allErrors) { this.allErrors = allErrors; } public void handle(Validatable validatable, ValidationContext context) { handleValidation(validatable, context); ConfigErrors configErrors = validatable.errors(); if (!configErrors.isEmpty()) { allErrors.add(configErrors); } } public abstract void handleValidation(Validatable validatable, ValidationContext context); } private List<ConfigErrors> getAllErrors(Validatable v) { final List<ConfigErrors> allErrors = new ArrayList<ConfigErrors>(); new GoConfigGraphWalker(v) .walk( new ErrorCollectingHandler(allErrors) { @Override public void handleValidation(Validatable validatable, ValidationContext context) { // do nothing here } }); return allErrors; } private void setupPipelines(Integer numberOfPipelinesToBeCreated) throws Exception { String groupName = "jumbo"; String configFile = "<FULL PATH TO YOUR CONFIG FILE>"; String xml = FileUtil.readContentFromFile(new File(configFile)); xml = goConfigMigration.upgradeIfNecessary(xml); goConfigService .fileSaver(false) .saveConfig(xml, goConfigService.getConfigForEditing().getMd5()); LOGGER.info( String.format( "Total number of pipelines in this config: %s", goConfigService.getConfigForEditing().allPipelines().size())); if (goConfigService.getConfigForEditing().hasPipelineGroup(groupName)) { ((BasicPipelineConfigs) goConfigService.getConfigForEditing().findGroup(groupName)).clear(); } final CruiseConfig configForEditing = goConfigService.getConfigForEditing(); for (int i = 0; i < numberOfPipelinesToBeCreated; i++) { JobConfig jobConfig = new JobConfig(new CaseInsensitiveString("job")); StageConfig stageConfig = new StageConfig(new CaseInsensitiveString("stage"), new JobConfigs(jobConfig)); PipelineConfig pipelineConfig = new PipelineConfig( new CaseInsensitiveString("pipeline" + i), new MaterialConfigs(new GitMaterialConfig("FOO")), stageConfig); configForEditing.addPipeline(groupName, pipelineConfig); } goConfigService.updateConfig( new UpdateConfigCommand() { @Override public CruiseConfig update(CruiseConfig cruiseConfig) throws Exception { return configForEditing; } }); } }