text:
/**
 * (c) 2017 TIBCO Software Inc. All rights reserved.
 *
 * Except as specified below, this software is licensed pursuant to the Eclipse Public License v. 1.0.
 * The details can be found in the file LICENSE.
 *
 * The following proprietary files are included as a convenience, and may not be used except pursuant
 * to valid license to Composite Information Server or TIBCO(R) Data Virtualization Server:
 * csadmin-XXXX.jar, csarchive-XXXX.jar, csbase-XXXX.jar, csclient-XXXX.jar, cscommon-XXXX.jar,
 * csext-XXXX.jar, csjdbc-XXXX.jar, csserverutil-XXXX.jar, csserver-XXXX.jar, cswebapi-XXXX.jar,
 * and customproc-XXXX.jar (where -XXXX is an optional version number).  Any included third party files
 * are licensed under the terms contained in their own accompanying LICENSE files, generally named .LICENSE.txt.
 *
 * This software is licensed AS-IS. Support for this software is not covered by standard maintenance agreements with TIBCO.
 * If you would like to obtain assistance with this software, such assistance may be obtained through a separate paid consulting
 * agreement with TIBCO.
 *
 */
package com.tibco.ps.deploytool.dao.jdbcapi;

import java.sql.Connection;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.net.Authenticator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.tibco.ps.common.BasicAuthenticator;
import com.tibco.ps.common.exception.CompositeException;
import com.tibco.ps.common.util.CommonUtils;
import com.tibco.ps.common.util.jdbcapi.JdbcConnector;
import com.tibco.ps.common.util.wsapi.CompositeServer;
import com.tibco.ps.deploytool.dao.RegressionPubTestDAO;
import com.tibco.ps.deploytool.services.RegressionItem;
import com.tibco.ps.deploytool.services.RegressionManagerImpl;
import com.tibco.ps.deploytool.services.RegressionManagerUtils;
import com.tibco.ps.deploytool.modules.RegressionTestType;

/**
 * This class is based in the original Pubtest utility. Is uses most its functionality;
 * modifications were made in exception types, parameter passing, and JDBC connection
 * handling.
 *
 * @author sst
 * @modified
 * 	2013-02-13 (mtinius): added support for variables for all fields in RegressionModule.xml
 *  2013-11-27 (mtinius): resolved resource URLs with spaces and periods.  Added better support for parsing complex FROM clauses.
 *  2014-01-09 (mtinius): changed code to replace "\n" with space " " for queries and procedures so as to support multi-line sql without the query failing during execution.
 *  							From: query = item.input.replaceAll("\n", "");
 *  							  To: query = item.input.replaceAll("\n", " ");
 */
public class RegressionPubTestJdbcDAOImpl implements RegressionPubTestDAO
{
	private static Log logger = LogFactory.getLog(RegressionPubTestJdbcDAOImpl.class);
	private static String propertyFile = RegressionManagerImpl.propertyFile;

 	/**
	 *  Map of published datasource names to established JDBC connections to CIS
	 */
	private HashMap<String,Connection> cisConnections = null;

    String logDelim = "|"; // Delimiter character

    private RegressionItem item;
	private CompositeServer cisServerConfig = null;
	private RegressionTestType regressionConfig = null;
	// Use these default queries if the <newFileParams> is not in the regression XML.
    private String publishedViewQry = "SELECT count(1) cnt FROM";
    private String publishedProcQry = "SELECT count(*) cnt FROM";

	// Test Types from Regression XML schema
    static final String FUNCTIONAL = "functional";
    static final String FUNCTIONAL_AS_IS = "functional_as_is";
    static final String REGRESSION = "regression";
    static final String MIGRATION = "migration";
    static final String PERFORMANCE = "performance";

	/**
	 * This implementation differs from the original Pubtest utility in that
	 * here we don't create a new JDBC connection for every query or procedure
	 * or WS. Instead, we create one connection per published data source and keep
	 * these connections open for the duration of the test. When, for example,
	 * a query is found in the input file, its datasource name is looked up in
	 * the list of connections and corresponding connection is used. That way
	 * we still execute on a connection to a specific published data source,
	 * but we don't open and close a lot of connections all the time during the test.
	 *
	 * also @see com.tibco.ps.deploytool.dao.RegressionPubTestDAO#executeAll()
	 */
//	@Override
	public void executeAll(CompositeServer cisServerConfig, RegressionTestType regressionConfig) throws CompositeException
	{
// 0. Check the input parameter values:
		if (cisServerConfig == null || regressionConfig == null)
		{
			throw new CompositeException(
					"XML Configuration objects are not initialized " +
					"when trying to run Regression test.");
		}
		if (this.cisServerConfig == null)	{	this.cisServerConfig = cisServerConfig;	}
		if (this.regressionConfig == null)	{	this.regressionConfig = regressionConfig; }

// To do: take a look at the authenticator from the original pubtest
		Authenticator.setDefault(new BasicAuthenticator(cisServerConfig));

		// Initialize start time and format
        Date startDate = new Date();
        Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

// 1. Initialize configuration items:
        String prefix = "executeAll";
        // Get items from config file:
		// Get input file path
		String inputFilePath =  CommonUtils.extractVariable(prefix, regressionConfig.getInputFilePath(), propertyFile, true);
		// Test for zero length before testing for null
		if (inputFilePath != null && inputFilePath.length() == 0)
			inputFilePath = null;
		// Now test for null
		if (inputFilePath == null)
			throw new CompositeException("Input file path is not defined in the regression XML file.");

		// Get the base directory where the files should be stored
		String baseDir = null;
		if ( regressionConfig.getTestRunParams().getBaseDir() != null) {
			baseDir = CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getBaseDir().trim(), propertyFile, true);
	        if (baseDir != null && baseDir.length() > 0) {
	        	baseDir = baseDir.replaceAll(Matcher.quoteReplacement("\\\\"), Matcher.quoteReplacement("/"));
	        	baseDir = baseDir.replaceAll(Matcher.quoteReplacement("\\"), Matcher.quoteReplacement("/"));
		        // Make the sub-directory for the base directory which is where the result files go for each execution
		        boolean res = CommonUtils.mkdirs(baseDir);
	        } else {
	        	baseDir = null;
	        }
		}

        // Get log file delimiter
		if ( regressionConfig.getTestRunParams().getLogDelimiter() != null) {
			logDelim = RegressionManagerUtils.getDelimiter(CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getLogDelimiter().toString(), propertyFile, false));
		}

        // Get output file delimiter
        String outputDelimiter = "|";
		if ( regressionConfig.getTestRunParams().getDelimiter() != null) {
			outputDelimiter = RegressionManagerUtils.getDelimiter(CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getDelimiter().toString(), propertyFile, false));
		}

		// Get the printOutput variable
		String printOutputType = "verbose";
		if (regressionConfig.getTestRunParams().getPrintOutput() != null)
			printOutputType = CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getPrintOutput(), propertyFile, false);

        // Get the regression log location
    	String logFilePath = CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getLogFilePath(), propertyFile, true);
        if (logFilePath == null || logFilePath.length() == 0) {
			throw new CompositeException("The log file path testRunParams.logFilePath may not be null or empty in the regression XML file.");
        }
        String logAppend = CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getLogAppend(), propertyFile, false);
        if (logAppend == null || logAppend.length() == 0) {
			throw new CompositeException("The log file append testRunParams.logAppend may not be null or empty in the regression XML file.");
        }

        String testType = CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getTestType(), propertyFile, false);
        if (FUNCTIONAL.equalsIgnoreCase(testType))
        {
        	if (regressionConfig.getNewFileParams() != null) {
        		if (regressionConfig.getNewFileParams().getPublishedViewQry() != null && regressionConfig.getNewFileParams().getPublishedViewQry().length() > 0) {
        			publishedViewQry = CommonUtils.extractVariable(prefix, regressionConfig.getNewFileParams().getPublishedViewQry(), propertyFile, false);
        		}
        		if (regressionConfig.getNewFileParams().getPublishedProcQry() != null && regressionConfig.getNewFileParams().getPublishedProcQry().length() > 0) {
        			publishedProcQry = CommonUtils.extractVariable(prefix, regressionConfig.getNewFileParams().getPublishedProcQry(), propertyFile, false);
        		}
        	}

        }

/* Construct the log header content
 *
 * Result  |ExecutionStartTime        |Duration            |Rows                |Database                      |Query                                                                 |Type       |OutputFile                                        |Message
 * SKIPPED |2012-06-08 10:28:28.0630  |000 00:00:00.0000   |0                   |MYTEST                        |SELECT * FROM CAT1.SCH2.ViewSales WHERE ProductName like 'Mega%'      |QUERY      |C:/tmp/cis51/MYTEST/CAT1.SCH2.ViewSales.txt       |
 * SUCCESS |2012-06-08 10:28:28.0692  |000 00:00:00.0016   |1                   |MYTEST                        |SELECT * FROM getProductName(1)                                       |PROCEDURE  |C:/tmp/cis51/MYTEST/getProductName.txt            |
 * ERROR   |2012-05-09 01:00:00.000   |000 00:00:01.000    |0                   |MYDB                          |select count(*) from cat1.sch1.P1                                     |PROCEDURE  |C:/tmp/51/cat1.sch1.P1                            |<failure message if exists>
 */
        String padChar = " "; // pad characters
        String content =
	       	CommonUtils.rpad("Result", 				 8, padChar)+logDelim +
	    	CommonUtils.rpad("ExecutionStartTime", 	26, padChar)+logDelim +
	    	CommonUtils.rpad("Duration", 			20, padChar)+logDelim +
	    	CommonUtils.rpad("Rows", 				20, padChar)+logDelim +
	    	CommonUtils.rpad("Database", 			30, padChar)+logDelim +
	    	CommonUtils.rpad("Query", 				70, padChar)+logDelim +
	    	CommonUtils.rpad("Type", 				11, padChar)+logDelim +
	    	CommonUtils.rpad("OutputFile",			50, padChar)+logDelim +
	    	"Message"+"\r\n";

        // Write out the header log entry -- if it does not exist the sub-directories will automatically be created.
        if (RegressionManagerUtils.checkBooleanConfigParam(logAppend)) {
	        	CommonUtils.appendContentToFile(logFilePath, content);
         } else {
        	// create a new file
        	CommonUtils.createFileWithContent(logFilePath, content);
        }

		// Check to see what should be executed
		boolean runQueries = RegressionManagerUtils.checkBooleanConfigParam(CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getRunQueries(), propertyFile, false));
		boolean runProcs = RegressionManagerUtils.checkBooleanConfigParam(CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getRunProcedures(), propertyFile, false));
		boolean runWs = RegressionManagerUtils.checkBooleanConfigParam(CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getRunWS(), propertyFile, false));
		boolean useAllDatasources = RegressionManagerUtils.checkBooleanConfigParam(CommonUtils.extractVariable(prefix, regressionConfig.getTestRunParams().getUseAllDatasources(), propertyFile, false));

		// Get the list of items from the input file
        RegressionItem[] items = RegressionManagerUtils.parseItems(inputFilePath);

        // Initialize counters
        //   Initialize Success Counters
		int totalSuccessTests = 0;
		int totalSuccessQueries = 0;
		int totalSuccessProcs = 0;
		int totalSuccessWS = 0;
		//   Initialize Skipped Counters
		int totalSkippedTests = 0;
		int totalSkippedQueries = 0;
		int totalSkippedProcs = 0;
		int totalSkippedWS = 0;
		//   Initialize Error Counters
		int totalFailedTests = 0;
		int totalFailedQueries = 0;
		int totalFailedProcs = 0;
		int totalFailedWS = 0;

// 2. Execute items:
        // Execute each item from the input file
        for (int i=0; i<items.length; i++)
        {
        	// Initialize the item object
        	item = items[i];

        	String outputFile = null;
           	String result = "SKIPPED"; // [SKIPPED,SUCCESS,ERROR]
        	String duration = "";
        	String database = item.database;
        	String outputFilename = item.outputFilename;
        	int rows = 0;
        	String query = "";
        	String resourceType = "";
           	String resourceURL = "";
           	String uniqueReourceURL = "";

        	// Execute Queries
        	if (item.type == RegressionManagerUtils.TYPE_QUERY) {
            	resourceType = "QUERY";

            	query = item.input.replaceAll("\n", " ");

            	// Retrieve only the FROM clause table URL with no where clause and no SELECT * FROM projections
            	resourceURL = RegressionManagerUtils.getTableUrl(query);

            	// mtinius 2015-10-13: Fixed execute smoke test issue by adding checksum to a separate "uniqueResourceURL" variable instead of the original "resourceURL".
        		uniqueReourceURL = RegressionManagerUtils.appendUrlChecksum(item.input, resourceURL);

        		if (outputFilename == null || outputFilename.length() == 0)
            		outputFilename = uniqueReourceURL + ".txt";

            	// Only use the this for functional testing.  It forces PDTool to use the standard SELECT COUNT(*) + FROM clause and ignores the query in the input file.
            	if (FUNCTIONAL.equalsIgnoreCase(testType))
            	{
            		query = publishedViewQry + " " + resourceURL;
            	}
        		item.input = query;

            	// Derive the base directory for the output file (remove any double quotes from the file name).
            	if (baseDir != null)
            		outputFile = (baseDir + "/" + database.replaceAll("\"", "") + "/" + outputFilename).replaceAll("//", "/");
        	}
        	// Execute Procedures
        	if (item.type == RegressionManagerUtils.TYPE_PROCEDURE) {
            	resourceType = "PROCEDURE";

            	query = item.input.replaceAll("\n", " ");

            	// Retrieve only the FROM clause procedure URL with no where clause and no SELECT * FROM projections and no parameters.
            	resourceURL = RegressionManagerUtils.getTableUrl(query);

            	// mtinius 2015-10-13: Fixed execute smoke test issue by adding checksum to a separate "uniqueResourceURL" variable instead of the original "resourceURL".
        		uniqueReourceURL = RegressionManagerUtils.appendUrlChecksum(item.input, resourceURL);

            	if (outputFilename == null || outputFilename.length() == 0)
            		outputFilename = uniqueReourceURL + ".txt";

             	// Only use the this for functional testing.  It forces PDTool to use the standard SELECT COUNT(*) + FROM clause and ignores the query in the input file.
            	if (FUNCTIONAL.equalsIgnoreCase(testType))
            	{
            		query = publishedProcQry + " " + RegressionManagerUtils.getProcedure(query);
            	}

            	item.input = query;

            	// Derive the base directory for the output file (remove any double quotes from the file name).
            	if (baseDir != null)
            		outputFile = (baseDir + "/" + database.replaceAll("\"", "") + "/" + outputFilename).replaceAll("//", "/");
        	}
        	// Execute Web Services
        	if (item.type == RegressionManagerUtils.TYPE_WS) {
            	resourceType = "WS";
            	query = (item.path+ "/" + item.action).replaceAll("//", "/");
            	resourceURL = (item.path + "/" + item.action).replaceAll("//", "/").replaceAll("/", "."); // construct ws path from the path and action combined.
            	if (resourceURL.indexOf(".") == 0)
            		resourceURL = resourceURL.substring(1);

            	// mtinius 2015-10-13: Fixed execute smoke test issue by adding checksum to a separate "uniqueResourceURL" variable instead of the original "resourceURL".
        		uniqueReourceURL = RegressionManagerUtils.appendUrlChecksum(item.input, resourceURL);

        		if (outputFilename == null || outputFilename.length() == 0)
            		outputFilename = uniqueReourceURL + ".txt";

               	// Derive the base directory for the output file (remove any double quotes from the file name).
            	if (baseDir != null)
            		outputFile = (baseDir + "/" + database.replaceAll("\"", "") + "/" + outputFilename).replaceAll("//", "/");
        	}

        	String message = "";
            Date beginDate = new Date();
        	String executionStartTime = formatter.format(beginDate);

        	/*
        	 *  If testRunParams.useAllDatasources is set to true in then use all datasource queries in the input file
        	 *  otherwise determine if the database in the input file is in the testRunParams.datasource list in the XML file
        	 *  and process it if it is.
        	 *
        	 *  See if database exists in this list then process if it is.
        	 * 			<datasources>
			 *				<dsName>MYTEST</dsName>
			 *				<dsName>testWebService00</dsName>
			 *			</datasources>
        	 */
        	boolean databaseMatch = true;
        	if (!useAllDatasources)
        		databaseMatch = RegressionManagerUtils.findDatabaseMatch(database, regressionConfig.getTestRunParams().getDatasources(), propertyFile);

			/* Determine if the specific resource should be compared by checking the XML resource list.
			 * If the resourceURL pattern matches what is in this list then process it.
			 * 		<resources>
			 *			<resource>TEST1.*</resource>
			 *			<resource>TEST1.SCH.*</resource>
			 *			<resource>TEST1.SCH.VIEW1</resource>
			 *		</resources>
			 */
        	boolean resourceMatch = RegressionManagerUtils.findResourceMatch(resourceURL, regressionConfig.getTestRunParams().getResources(), propertyFile);

        	try
            {
            	RegressionManagerUtils.printOutputStr(printOutputType, "summary", "------------------------ Test "+(i+1)+" -----------------------------","Test "+(i+1)+" ... ");
                if (item.type == RegressionManagerUtils.TYPE_QUERY && runQueries && databaseMatch && resourceMatch)
                {
                	// Initialize the file
                    if (outputFile != null)
                    	CommonUtils.createFileWithContent(outputFile, "");

                    // Establish a JDBC connection for this database
    	            cisConnections = RegressionManagerUtils.establishJdbcConnection(item.database, cisConnections, cisServerConfig, regressionConfig, propertyFile);  // don't need to check for null here.

    	            // Print out the line to the command line
    		        RegressionManagerUtils.printOutputStr(printOutputType, "summary", "Execute Query:  " + item.input + "\n", "");

                	String r = RegressionManagerUtils.executeQuery(item, cisConnections, outputFile, outputDelimiter, printOutputType);
                	String results[] = r.split(":");
                	if (results.length > 1) {
                		rows = Integer.valueOf(results[0]);
                	}

                    result = "SUCCESS";
                    totalSuccessTests++;
                    totalSuccessQueries++;
                }
                else if (item.type == RegressionManagerUtils.TYPE_PROCEDURE && runProcs && databaseMatch && resourceMatch)
                {
                	// Initialize the file
                    if (outputFile != null)
                    	CommonUtils.createFileWithContent(outputFile, "");

                    // Establish a JDBC connection for this database
    	            cisConnections = RegressionManagerUtils.establishJdbcConnection(item.database, cisConnections, cisServerConfig, regressionConfig, propertyFile);  // don't need to check for null here.

    	            // Print out the line to the command line
    		        RegressionManagerUtils.printOutputStr(printOutputType, "summary", "Execute Procedure:  " + item.input + "\n", "");

                    // Execute the procedure
                	String r = RegressionManagerUtils.executeProcedure(item, cisConnections, outputFile, outputDelimiter, printOutputType);
                	String results[] = r.split(":");
                	if (results.length > 1) {
                		rows = Integer.valueOf(results[0]);
                	}

                	result = "SUCCESS";
                    totalSuccessTests++;
                    totalSuccessProcs++;
                }
                else if (item.type == RegressionManagerUtils.TYPE_WS && runWs && databaseMatch && resourceMatch)
                {
                	// Initialize the file
                    if (outputFile != null)
                    	CommonUtils.createFileWithContent(outputFile, "");

                    // Print out the line to the command line
    		        RegressionManagerUtils.printOutputStr(printOutputType, "summary", "Execute Web Service:  " + item.path, "");
    		        RegressionManagerUtils.printOutputStr(printOutputType, "summary", item.input, "");

                    // Execute the web service
                	rows = RegressionManagerUtils.executeWs(item, outputFile, cisServerConfig, regressionConfig, outputDelimiter, printOutputType);

                    result = "SUCCESS";
                    totalSuccessTests++;
                    totalSuccessWS++;
                }
                else {
                	// Skip this test
                	if (item.type == RegressionManagerUtils.TYPE_WS)
                	{
                		totalSkippedWS++;
                		message = "  ::Reason: type="+resourceType+"  runWs="+runWs+"  databaseMatch="+databaseMatch+"  resourceMatch="+resourceMatch;
                		RegressionManagerUtils.printOutputStr(printOutputType, "summary", "Test Skipped: "+ resourceURL + message + "\n", "");
                	}
                	else if (item.type == RegressionManagerUtils.TYPE_QUERY)
                	{
                		totalSkippedQueries++;
                		message = "  ::Reason: type="+resourceType+"  runQueries="+runQueries+"  databaseMatch="+databaseMatch+"  resourceMatch="+resourceMatch;
                		RegressionManagerUtils.printOutputStr(printOutputType, "summary", "Test Skipped: "+ query + message + "\n", "");
                	}
                	else
                	{
                		totalSkippedProcs++;
                		message = "  ::Reason: type="+resourceType+"  runProcedures="+runProcs+"  databaseMatch="+databaseMatch+"  resourceMatch="+resourceMatch;
                		RegressionManagerUtils.printOutputStr(printOutputType, "summary", "Test Skipped: "+ query + message + "\n", "");
                	}
                	totalSkippedTests++;
                }
        	}
            catch (Exception e)
            {
                result = "ERROR";
            	if (item.type == RegressionManagerUtils.TYPE_WS)
            	{
            		totalFailedWS++;
            	}
            	else if (item.type == RegressionManagerUtils.TYPE_QUERY)
            	{
            		totalFailedQueries++;
            	}
            	else
            	{
            		totalFailedProcs++;
            	}
                totalFailedTests++;
                message = e.getMessage().replace("\n", " ").replaceAll("\r", " ");
                logger.error(message);
                logger.error("Item Input Details: "+item.toString());
            }

            // Setup content line to be output to the log file
            if (outputFile == null)
            	outputFile = "";
            duration = CommonUtils.getElapsedTime(beginDate);

            // Output the log entry
	        content =
	        	CommonUtils.rpad(result, 			 8, padChar)+logDelim +
	        	CommonUtils.rpad(executionStartTime,26, padChar)+logDelim +
	        	CommonUtils.rpad(duration.trim(),	20, padChar)+logDelim +
	        	CommonUtils.rpad(""+rows,	 		20, padChar)+logDelim +
	        	CommonUtils.rpad(database, 			30, padChar)+logDelim +
	        	CommonUtils.rpad(query, 			70, padChar)+logDelim +
	        	CommonUtils.rpad(resourceType, 		11, padChar)+logDelim +
	        	CommonUtils.rpad(outputFile,		50, padChar)+logDelim +
	        	message;

	        	CommonUtils.appendContentToFile(logFilePath, content);

        } // end of process input file items loop

        // Print out timings
        String duration = CommonUtils.getElapsedTime(startDate);

        String testTypeMessage = "";
        if (FUNCTIONAL.equalsIgnoreCase(testType))
        	testTypeMessage = "Execute a default query: SELECT COUNT(1) FROM...";
        if (FUNCTIONAL_AS_IS.equalsIgnoreCase(testType))
        	testTypeMessage = "Execute a full query from the query list.";
        if (REGRESSION.equalsIgnoreCase(testType))
        	testTypeMessage = "Execute a full query from the query list.";
        if (MIGRATION.equalsIgnoreCase(testType))
        	testTypeMessage = "Execute a full query from the query list.";

        		 int len = 56;
				 logger.info("--------------------------------------------------------");
				 logger.info("---------- Regression Published Test Summary -----------");
				 logger.info("--------------------------------------------------------");
logger.info(CommonUtils.rpad("Test Type: " + testType, len, " "));
logger.info(CommonUtils.rpad("  " + testTypeMessage, len, " "));
				 logger.info("                                                        ");
logger.info(CommonUtils.rpad("Total Successful        Queries: " + totalSuccessQueries, len, " "));
logger.info(CommonUtils.rpad("Total Successful     Procedures: " + totalSuccessProcs, len, " "));
logger.info(CommonUtils.rpad("Total Successful   Web Services: " + totalSuccessWS, len, " "));
				 logger.info("                                 ---------              ");
logger.info(CommonUtils.rpad("Total Successful -------> Tests: " + totalSuccessTests, len, " "));
				 logger.info("                                                        ");
logger.info(CommonUtils.rpad("Total Skipped           Queries: " + totalSkippedQueries, len, " "));
logger.info(CommonUtils.rpad("Total Skipped        Procedures: " + totalSkippedProcs, len, " "));
logger.info(CommonUtils.rpad("Total Skipped      Web Services: " + totalSkippedWS, len, " "));
				 logger.info("                                 ---------              ");
logger.info(CommonUtils.rpad("Total Skipped ----------> Tests: " + totalSkippedTests, len, " "));
				 logger.info("                                                        ");
logger.info(CommonUtils.rpad("Total Failed            Queries: " + totalFailedQueries, len, " "));
logger.info(CommonUtils.rpad("Total Failed         Procedures: " + totalFailedProcs, len, " "));
logger.info(CommonUtils.rpad("Total Failed       Web Services: " + totalFailedWS, len, " "));
				 logger.info("                                 ---------              ");
logger.info(CommonUtils.rpad("Total Failed -----------> Tests: " + totalFailedTests, len, " "));
				 logger.info("                                                        ");
logger.info(CommonUtils.rpad("Total Combined ---------> Tests: " + (totalSuccessTests+totalSkippedTests+totalFailedTests), len, " "));
				 logger.info("                                                        ");
logger.info(CommonUtils.rpad("        Published Test duration: " + duration, len, " "));
				 logger.info("                                                        ");
				 logger.info("Review \"pubtest\" Summary: " + logFilePath);
				 logger.info("--------------------------------------------------------");

		String moduleActionMessage = "MODULE_INFO: Regression Summary: Successful="+totalSuccessTests+" Skipped="+totalSkippedTests+" Failed="+totalFailedTests;
		System.setProperty("MODULE_ACTION_MESSAGE", moduleActionMessage);

// 3. Close all connections:
        JdbcConnector connector = new JdbcConnector();
        if (this.cisConnections != null)
        {
        	for(Connection nextConnection : this.cisConnections.values())  // getting all non-null values
        	{
        		connector.closeJdbcConnection(nextConnection);
        	}
        	this.cisConnections = null;
        }
    	RegressionManagerUtils.printOutputStr(printOutputType, "summary", "\nCompleted ExecuteAll()", "");
	} // end method

}


text:
package com.testclient.model;

import java.util.HashMap;
import java.util.Map;

import com.testclient.httpmodel.CheckPointItem;

public class CheckPointContianer {
	Map<String,CheckPointItem> checkPoint= new HashMap<String,CheckPointItem>();

	public Map<String, CheckPointItem> getCheckPoint() {
		return checkPoint;
	}

	public void setCheckPoint(Map<String, CheckPointItem> checkPoint) {
		this.checkPoint = checkPoint;
	}

}

redpajama_set_name: RedPajamaGithub


text:
package iso20022

// Information related to a linked transaction.
type Linkages2 struct {

	// When the transaction is to be executed relative to a linked transaction.
	ProcessingPosition *ProcessingPosition1Choice `xml:"PrcgPos,omitempty"`

	// Message type number/message identifier of the message referenced in the linkage sequence.
	MessageNumber *DocumentNumber1Choice `xml:"MsgNb,omitempty"`

	// Reference to the linked transaction.
	Reference *References1Choice `xml:"Ref"`
}

func (l *Linkages2) AddProcessingPosition() *ProcessingPosition1Choice {
	l.ProcessingPosition = new(ProcessingPosition1Choice)
	return l.ProcessingPosition
}

func (l *Linkages2) AddMessageNumber() *DocumentNumber1Choice {
	l.MessageNumber = new(DocumentNumber1Choice)
	return l.MessageNumber
}

func (l *Linkages2) AddReference() *References1Choice {
	l.Reference = new(References1Choice)
	return l.Reference
}


text:
require 'test_helper'

class ScheduleBookerTest < ActiveSupport::TestCase
  test "schedule booker" do
    schedule_booker = ScheduleBooker.new
    schedule_booker.booking.must_be_kind_of Booking
  end

  test "schedule booker should not save if unavailable" do
    schedule = create(:sold_out_schedule)
    schedule_booker = ScheduleBooker.new(booking: { schedule_id: schedule.id},
                                         travelers: { name: "Oliver" })
    schedule_booker.save.must_equal false
  end
end


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MickeySmith;
using Shouldly;
using TestStack.BDDfy;
using Xunit;

namespace Tests.Delete
{
    public class ItDeletesAKey
    {
        private readonly Session _session = SessionFactory.GetSession();
        private const string _key = "ItDeletesAKey";

        [Fact]
        public void GivenAPresentKeyValueWhenDeletingTheKeyTheValueIsNull()
        {
            this
                .Given(x => x.GivenAPresentKey())
                .When(x => x.WhenDeletingTheKey())
                .Then(x => x.ThenTheValueIsNull())
                .BDDfy();
        }

        void GivenAPresentKey()
        {
            _session.Set(_key, "value");
        }

        void WhenDeletingTheKey()
        {
            _session.Delete(_key);
        }

        void ThenTheValueIsNull()
        {
            ((object)_session.Get(_key)).ShouldBe(null);
        }
    }
}


text:
package cn.featherfly.conversion.core.basic;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import cn.featherfly.common.lang.GenericType;
import cn.featherfly.common.lang.StringUtils;
import cn.featherfly.conversion.core.ConversionException;

/**
 * <p>
 * LocalDate类转换器
 * </p>
 *
 * @author 钟冀
 */
public class LocalDateConvertor extends AbstractBasicConvertor<LocalDate, GenericType<LocalDate>> {

	private static final String DATE_TIME_FORMAT = "yyyy-MM-dd";

	private static final DateTimeFormatter DATE_TIME_PATTERN = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);

	/**
	 */
	public LocalDateConvertor() {
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected String doToString(LocalDate value, GenericType<LocalDate> genericType) {
		if (value != null) {
			return value.format(DATE_TIME_PATTERN);
		}
		return "";
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected LocalDate doToObject(String value, GenericType<LocalDate> genericType) {
		if (StringUtils.isNotBlank(value)) {
			value = value.trim();
			try {
				return LocalDate.parse(value, DATE_TIME_PATTERN);
			} catch (Exception e) {
				throw new ConversionException("#convert_failed_with_type",
						new Object[] { value, DATE_TIME_FORMAT, getType().getName() });
			}
		}
		return null;
	}

}


text:
<?php

/**
 * @file
 * Definition of Drupal\user\RegisterFormController.
 */

namespace Drupal\user;

use Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * Form controller for the user register forms.
 */
class RegisterFormController extends AccountFormController {

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::form().
   */
  public function form(array $form, array &$form_state) {
    global $user;
    $account = $this->entity;

    $admin = user_access('administer users');

    // Pass access information to the submit handler. Running an access check
    // inside the submit function interferes with form processing and breaks
    // hook_form_alter().
    $form['administer_users'] = array(
      '#type' => 'value',
      '#value' => $admin,
    );

    // If we aren't admin but already logged on, go to the user page instead.
    if (!$admin && $user->isAuthenticated()) {
      return new RedirectResponse(url('user/' . $user->id(), array('absolute' => TRUE)));
    }

    $form['#attached']['library'][] = array('system', 'jquery.cookie');
    $form['#attributes']['class'][] = 'user-info-from-cookie';

    // Start with the default user account fields.
    $form = parent::form($form, $form_state, $account);

    // Attach field widgets.
    field_attach_form($account, $form, $form_state);

    if ($admin) {
      // Redirect back to page which initiated the create request; usually
      // admin/people/create.
      $form_state['redirect'] = current_path();
    }

    return $form;
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::actions().
   */
  protected function actions(array $form, array &$form_state) {
    $element = parent::actions($form, $form_state);
    $element['submit']['#value'] = t('Create new account');
    return $element;
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::submit().
   */
  public function submit(array $form, array &$form_state) {
    $admin = $form_state['values']['administer_users'];

    if (!config('user.settings')->get('verify_mail') || $admin) {
      $pass = $form_state['values']['pass'];
    }
    else {
      $pass = user_password();
    }

    // Remove unneeded values.
    form_state_values_clean($form_state);

    $form_state['values']['pass'] = $pass;
    $form_state['values']['init'] = $form_state['values']['mail'];

    parent::submit($form, $form_state);
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::submit().
   */
  public function save(array $form, array &$form_state) {
    $account = $this->entity;
    $pass = $account->getPassword();
    $admin = $form_state['values']['administer_users'];
    $notify = !empty($form_state['values']['notify']);

    // Save has no return value so this cannot be tested.
    // Assume save has gone through correctly.
    $account->save();

    $form_state['user'] = $account;
    $form_state['values']['uid'] = $account->id();

    watchdog('user', 'New user: %name %email.', array('%name' => $form_state['values']['name'], '%email' => '<' . $form_state['values']['mail'] . '>'), WATCHDOG_NOTICE, l(t('edit'), 'user/' . $account->id() . '/edit'));

    // Add plain text password into user account to generate mail tokens.
    $account->password = $pass;

    // New administrative account without notification.
    $uri = $account->uri();
    if ($admin && !$notify) {
      drupal_set_message(t('Created a new user account for %name. No e-mail has been sent.', array('@url' => url($uri['path'], $uri['options']), '%name' => $account->getUsername())));
    }
    // No e-mail verification required; log in user immediately.
    elseif (!$admin && !config('user.settings')->get('verify_mail') && $account->isActive()) {
      _user_mail_notify('register_no_approval_required', $account);
      user_login_finalize($account);
      drupal_set_message(t('Registration successful. You are now logged in.'));
      $form_state['redirect'] = '';
    }
    // No administrator approval required.
    elseif ($account->isActive() || $notify) {
      if (!$account->getEmail() && $notify) {
        drupal_set_message(t('The new user %name was created without an email address, so no welcome message was sent.', array('@url' => url($uri['path'], $uri['options']), '%name' => $account->getUsername())));
      }
      else {
        $op = $notify ? 'register_admin_created' : 'register_no_approval_required';
        if (_user_mail_notify($op, $account)) {
          if ($notify) {
            drupal_set_message(t('A welcome message with further instructions has been e-mailed to the new user %name.', array('@url' => url($uri['path'], $uri['options']), '%name' => $account->getUsername())));
          }
          else {
            drupal_set_message(t('A welcome message with further instructions has been sent to your e-mail address.'));
            $form_state['redirect'] = '';
          }
        }
      }
    }
    // Administrator approval required.
    else {
      _user_mail_notify('register_pending_approval', $account);
      drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.
In the meantime, a welcome message with further instructions has been sent to your e-mail address.'));
      $form_state['redirect'] = '';
    }
  }
}


text:
import {dev, user} from '../log';
import {fromClass} from '../service';
import {
  getSourceOrigin,
  getCorsUrl,
  parseUrl,
} from '../url';
import {isArray, isObject, isFormData} from '../types';

/**
 * The "init" argument of the Fetch API. Currently, only "credentials: include"
 * is implemented.
 *
 * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
 *
 * @typedef {{
 *   body: (!Object|!Array|undefined|string),
 *   credentials: (string|undefined),
 *   headers: (!Object|undefined),
 *   method: (string|undefined),
 *   requireAmpResponseSourceOrigin: (boolean|undefined)
 * }}
 */
let FetchInitDef;

/** @private @const {!Array<string>} */
const allowedMethods_ = ['GET', 'POST'];

/** @private @const {!Array<function(*):boolean>} */
const allowedJsonBodyTypes_ = [isArray, isObject];

/** @private @enum {number} Allowed fetch responses. */
const allowedFetchTypes_ = {
  document: 1,
  text: 2,
  arraybuffer: 3,
};

/** @private @const {string} */
const ALLOW_SOURCE_ORIGIN_HEADER = 'AMP-Access-Control-Allow-Source-Origin';

/**
 * A service that polyfills Fetch API for use within AMP.
 *
 * @package Visible for type.
 * @visibleForTesting
 */
export class Xhr {

  /**
   * @param {!Window} win
   */
  constructor(win) {
    /** @const {!Window} */
    this.win = win;
  }

  /**
   * We want to call `fetch_` unbound from any context since it could
   * be either the native fetch or our polyfill.
   *
   * @param {string} input
   * @param {!FetchInitDef=} opt_init
   * @return {!Promise<!FetchResponse>|!Promise<!Response>}
   * @private
   */
  fetch_(input, opt_init) {
    dev().assert(typeof input == 'string', 'Only URL supported: %s', input);
    if (opt_init && opt_init.credentials !== undefined) {
      // In particular, Firefox does not tolerate `null` values for
      // `credentials`.
      dev().assert(opt_init.credentials == 'include',
          'Only credentials=include support: %s', opt_init.credentials);
    }
    // Fallback to xhr polyfill since `fetch` api does not support
    // responseType = 'document'. We do this so we don't have to do any parsing
    // and document construction on the UI thread which would be expensive.
    if (opt_init && opt_init.responseType == 'document') {
      return fetchPolyfill(input, opt_init);
    }
    return (this.win.fetch || fetchPolyfill).apply(null, arguments);
  }

  /**
   * Performs the final initialization and requests the fetch. It does three
   * main things: (1) It adds "__amp_source_origin" URL parameter with source
   * origin; (2) It verifies "AMP-Access-Control-Allow-Source-Origin" if it's
   * returned in the response; and (3) It requires
   * "AMP-Access-Control-Allow-Source-Origin" to be present in the response
   * if the `init.requireAmpResponseSourceOrigin = true`.
   *
   * @param {string} input
   * @param {!FetchInitDef=} opt_init
   * @return {!Promise<!FetchResponse>}
   * @private
   */
  fetchAmpCors_(input, opt_init) {
    const init = opt_init || {};
    input = this.getCorsUrl(this.win, input);
    // For some same origin requests, add AMP-Same-Origin: true header to allow
    // publishers to validate that this request came from their own origin.
    const currentOrigin = parseUrl(this.win.location.href).origin;
    const targetOrigin = parseUrl(input).origin;
    if (currentOrigin == targetOrigin) {
      init['headers'] = init['headers'] || {};
      init['headers']['AMP-Same-Origin'] = 'true';
    }
    return this.fetch_(input, init).then(response => {
      const allowSourceOriginHeader = response.headers.get(
          ALLOW_SOURCE_ORIGIN_HEADER);
      if (allowSourceOriginHeader) {
        const sourceOrigin = getSourceOrigin(this.win.location.href);
        // If the `AMP-Access-Control-Allow-Source-Origin` header is returned,
        // ensure that it's equal to the current source origin.
        user().assert(allowSourceOriginHeader == sourceOrigin,
              `Returned ${ALLOW_SOURCE_ORIGIN_HEADER} is not` +
              ` equal to the current: ${allowSourceOriginHeader}` +
              ` vs ${sourceOrigin}`);
      } else if (init.requireAmpResponseSourceOrigin) {
        // If the `AMP-Access-Control-Allow-Source-Origin` header is not
        // returned but required, return error.
        user().assert(false, `Response must contain the` +
            ` ${ALLOW_SOURCE_ORIGIN_HEADER} header`);
      }
      return response;
    }, reason => {
      user().assert(false, 'Fetch failed %s: %s', input,
          reason && reason.message);
    });
  }

  /**
   * Fetches and constructs JSON object based on the fetch polyfill.
   *
   * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
   *
   * See `fetchAmpCors_` for more detail.
   *
   * @param {string} input
   * @param {?FetchInitDef=} opt_init
   * @return {!Promise<!JSONType>}
   */
  fetchJson(input, opt_init) {
    const init = opt_init || {};
    init.method = normalizeMethod_(init.method);
    setupJson_(init);
    return this.fetchAmpCors_(input, init).then(response => {
      return assertSuccess(response);
    }).then(response => response.json());
  }

  /**
   * Fetches text based on the fetch polyfill.
   *
   * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
   *
   * See `fetchAmpCors_` for more detail.
   *
   * @param {string} input
   * @param {?FetchInitDef=} opt_init
   * @return {!Promise<string>}
   */
  fetchText(input, opt_init) {
    const init = opt_init || {};
    init.method = normalizeMethod_(init.method);
    init.headers = init.headers || {};
    init.headers['Accept'] = 'text/plain';
    return this.fetchAmpCors_(input, init).then(response => {
      return assertSuccess(response);
    }).then(response => response.text());
  }

  /**
   * Creates an XHR request with responseType=document
   * and returns the `FetchResponse` object.
   *
   * @param {string} input
   * @param {?FetchInitDef=} opt_init
   * @return {!Promise<!Document>}
   */
  fetchDocument(input, opt_init) {
    const init = opt_init || {};
    init.responseType = 'document';
    init.method = normalizeMethod_(init.method);
    init.headers = init.headers || {};
    init.headers['Accept'] = 'text/html';

    return this.fetchAmpCors_(input, init).then(response => {
      return assertSuccess(response);
    }).then(response => response.document_());
  }

  /**
   * @param {string} input URL
   * @param {FetchInitDef} opt_init Fetch options object.
   * @return {!Promise<!FetchResponse>}
   */
  fetch(input, opt_init) {
    const init = opt_init || {};
    // The "real" fetch API does not specify the response type in the request.
    // The fetch response object lets you extract the body in any of the types.
    // Here, specify 'arraybuffer' in case we use the polyfill, since that is
    // what we will use when we use fetch.
    init.responseType = 'arraybuffer';
    init.method = normalizeMethod_(init.method);
    init.headers = init.headers || {};
    return this.fetchAmpCors_(input, init).then(response =>
      assertSuccess(response));
  }

  /**
   * Sends the request, awaits result and confirms that it was successful.
   *
   * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
   *
   * See `fetchAmpCors_` for more detail.
   *
   * @param {string} input
   * @param {!FetchInitDef=} opt_init
   * @return {!Promise}
   */
  sendSignal(input, opt_init) {
    return this.fetchAmpCors_(input, opt_init).then(response => {
      return assertSuccess(response);
    });
  }

  /**
   * Add "__amp_source_origin" query parameter to the URL. Ideally, we'd be
   * able to set a header (e.g. AMP-Source-Origin), but this will force
   * preflight request on all CORS request.
   * @param {!Window} win
   * @param {string} url
   * @return {string}
   */
  getCorsUrl(win, url) {
    return getCorsUrl(win, url);
  }

}

/**
 * Normalized method name by uppercasing.
 * @param {string|undefined} method
 * @return {string}
 * @private
 */
export function normalizeMethod_(method) {
  if (method === undefined) {
    return 'GET';
  }
  method = method.toUpperCase();

  dev().assert(
    allowedMethods_.indexOf(method) > -1,
    'Only one of %s is currently allowed. Got %s',
    allowedMethods_.join(', '),
    method
  );

  return method;
}

/**
* Initialize init object with headers and stringifies the body.
 * @param {!FetchInitDef} init
 * @private
 */
function setupJson_(init) {
  init.headers = init.headers || {};
  init.headers['Accept'] = 'application/json';

  if (init.method == 'POST' && !isFormData(init.body)) {
    // Assume JSON strict mode where only objects or arrays are allowed
    // as body.
    dev().assert(
      allowedJsonBodyTypes_.some(test => test(init.body)),
      'body must be of type object or array. %s',
      init.body
    );

    init.headers['Content-Type'] = 'application/json;charset=utf-8';
    init.body = JSON.stringify(init.body);
  }
}

/**
 * A minimal polyfill of Fetch API. It only polyfills what we currently use.
 *
 * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
 *
 * Notice that the "fetch" method itself is not exported as that would require
 * us to immediately support a much wide API.
 *
 * @param {string} input
 * @param {!FetchInitDef=} opt_init
 * @return {!Promise<!FetchResponse>}
 * @private Visible for testing
 */
export function fetchPolyfill(input, opt_init) {
  /** @type {!FetchInitDef} */
  const init = opt_init || {};
  return new Promise(function(resolve, reject) {
    const xhr = createXhrRequest(init.method || 'GET', input);

    if (init.credentials == 'include') {
      xhr.withCredentials = true;
    }

    if (init.responseType in allowedFetchTypes_) {
      xhr.responseType = init.responseType;
    }

    if (init.headers) {
      Object.keys(init.headers).forEach(function(header) {
        xhr.setRequestHeader(header, init.headers[header]);
      });
    }

    xhr.onreadystatechange = () => {
      if (xhr.readyState < /* STATUS_RECEIVED */ 2) {
        return;
      }
      if (xhr.status < 100 || xhr.status > 599) {
        xhr.onreadystatechange = null;
        reject(new Error(`Unknown HTTP status ${xhr.status}`));
        return;
      }

      // TODO(dvoytenko): This is currently simplified: we will wait for the
      // whole document loading to complete. This is fine for the use cases
      // we have now, but may need to be reimplemented later.
      if (xhr.readyState == /* COMPLETE */ 4) {
        resolve(new FetchResponse(xhr));
      }
    };
    xhr.onerror = () => {
      reject(new Error('Network failure'));
    };
    xhr.onabort = () => {
      reject(new Error('Request aborted'));
    };

    if (init.method == 'POST') {
      xhr.send(init.body);
    } else {
      xhr.send();
    }
  });
}

/**
 * @param {string} method
 * @param {string} url
 * @return {!XMLHttpRequest|!XDomainRequest}
 * @private
 */
function createXhrRequest(method, url) {
  let xhr = new XMLHttpRequest();
  if ('withCredentials' in xhr) {
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != 'undefined') {
    // IE-specific object.
    xhr = new XDomainRequest();
    xhr.open(method, url);
  } else {
    throw new Error('CORS is not supported');
  }
  return xhr;
}

/**
 * If 415 or in the 5xx range.
 * @param {string} status
 */
function isRetriable(status) {
  return status == 415 || (status >= 500 && status < 600);
}

/**
 * Returns the response if successful or otherwise throws an error.
 * @paran {!FetchResponse} response
 * @return {!Promise<!FetchResponse>}
 * @private Visible for testing
 */
export function assertSuccess(response) {
  return new Promise((resolve, reject) => {
    if (response.status < 200 || response.status >= 300) {
      /** @const {!Error} */
      const err = user().createError(`HTTP error ${response.status}`);
      if (isRetriable(response.status)) {
        err.retriable = true;
      }
      const contentType = response.headers.get('Content-Type') || '';
      if (contentType.split(';')[0] == 'application/json') {
        response.json().then(json => {
          err.responseJson = json;
          reject(err);
        }, () => {
          // Ignore a failed json parsing and just throw the error without
          // setting responseJson.
          reject(err);
        });
      } else {
        reject(err);
      }
    } else {
      resolve(response);
    }
  });
}

/**
 * Response object in the Fetch API.
 *
 * See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
 */
export class FetchResponse {
  /**
   * @param {!XMLHttpRequest|!XDomainRequest} xhr
   */
  constructor(xhr) {
    /** @private @const {!XMLHttpRequest|!XDomainRequest} */
    this.xhr_ = xhr;

    /** @type {number} */
    this.status = this.xhr_.status;

    /** @const {!FetchResponseHeaders} */
    this.headers = new FetchResponseHeaders(xhr);

    /** @type {boolean} */
    this.bodyUsed = false;
  }

  /**
   * Drains the response and returns the text.
   * @return {!Promise<string>}
   * @private
   */
  drainText_() {
    dev().assert(!this.bodyUsed, 'Body already used');
    this.bodyUsed = true;
    return Promise.resolve(this.xhr_.responseText);
  }

  /**
   * Drains the response and returns a promise that resolves with the response
   * text.
   * @return {!Promise<string>}
   */
  text() {
    return this.drainText_();
  }

  /**
   * Drains the response and returns the JSON object.
   * @return {!Promise<!JSONType>}
   */
  json() {
    return /** @type {!Promise<!JSONType>} */ (
        this.drainText_().then(JSON.parse.bind(JSON)));
  }

  /**
   * Reads the xhr responseXML.
   * @return {!Promise<!Document>}
   * @private
   */
  document_() {
    dev().assert(!this.bodyUsed, 'Body already used');
    this.bodyUsed = true;
    user().assert(this.xhr_.responseXML,
        'responseXML should exist. Make sure to return ' +
        'Content-Type: text/html header.');
    return /** @type {!Promise<!Document>} */ (
        Promise.resolve(dev().assert(this.xhr_.responseXML)));
  }

  /**
   * Drains the response and returns a promise that resolves with the response
   * ArrayBuffer.
   * @return {!Promise<!ArrayBuffer>}
   */
  arrayBuffer() {
    user().assert(this.xhr_.response, 'arrayBuffer response should exist.');
    dev().assert(this.xhr_.responseType == 'arraybuffer',
               'responseType was not "arraybuffer"');
    dev().assert(!this.bodyUsed, 'Body already used');
    this.bodyUsed = true;
    return /** @type {!Promise<!ArrayBuffer>} */ (
        Promise.resolve(this.xhr_.response));
  }
}

/**
 * Provides access to the response headers as defined in the Fetch API.
 * @private Visible for testing.
 */
export class FetchResponseHeaders {
  /**
   * @param {!XMLHttpRequest|!XDomainRequest} xhr
   */
  constructor(xhr) {
    /** @private @const {!XMLHttpRequest|!XDomainRequest} */
    this.xhr_ = xhr;
  }

  /**
   * @param {string} name
   * @return {*}
   */
  get(name) {
    return this.xhr_.getResponseHeader(name);
  }

  /**
   * @param {string} name
   * @return {boolean}
   */
  has(name) {
    return this.xhr_.getResponseHeader(name) != null;
  }
}

/**
 * @param {!Window} window
 * @return {!Xhr}
 */
export function installXhrService(window) {
  return fromClass(window, 'xhr', Xhr);
};


text:
from string import ascii_letters

import pytest

from nex.pydvi.TeXUnit import pt2sp
from nex.constants.codes import CatCode
from nex.constants.parameters import Parameters
from nex.constants.instructions import Instructions
from nex.banisher import (Banisher,
                          get_token_representation_integer,
                          get_str_representation_dimension,
                          get_token_representation_dimension)
from nex.router import (Instructioner,
                        make_unexpanded_control_sequence_instruction,
                        make_macro_token)
from nex.utils import ascii_characters, UserError

from common import DummyInstructions, ITok, char_instr_tok

test_char_to_cat = {}
for c in ascii_characters:
    test_char_to_cat[c] = CatCode.other
for c in ascii_letters:
    test_char_to_cat[c] = CatCode.letter
test_char_to_cat.update({
    '$': CatCode.escape,
    ' ': CatCode.space,
    '[': CatCode.begin_group,
    ']': CatCode.end_group,
    '\n': CatCode.end_of_line,
})

class DummyCodes:
    def __init__(self, char_to_cat):
        if char_to_cat is None:
            self.char_to_cat = test_char_to_cat.copy()
        else:
            self.char_to_cat = char_to_cat

    def get_cat_code(self, char):
        return self.char_to_cat[char]

    def get_lower_case_code(self, c):
        return c.lower()

    def get_upper_case_code(self, c):
        return c.upper()

class DummyRouter:

    def __init__(self, cs_map):
        self.cs_map = cs_map

    def lookup_control_sequence(self, name, *args, **kwargs):
        canon_token = self.cs_map[name]
        return canon_token.copy(*args, **kwargs)

    def name_means_start_condition(self, name):
        return name in ('ifYes', 'ifNo')

    def name_means_end_condition(self, name):
        return name == 'endIf'

    def name_means_delimit_condition(self, name):
        return name in ('else', 'ooor')

class DummyParameters:

    def __init__(self, param_map):
        self.param_map = param_map

    def get(self, name, *args, **kwargs):
        return self.param_map[name]

class DummyState:

    def __init__(self, char_to_cat, cs_map, param_map=None):
        self.router = DummyRouter(cs_map)
        self.parameters = DummyParameters(param_map)
        self.codes = DummyCodes(char_to_cat)

    def evaluate_if_token_to_block(self, tok):
        if tok.type == Instructions.if_true.value:
            return 0
        elif tok.type == Instructions.if_false.value:
            return 1
        else:
            raise Exception

def string_to_banisher(s, cs_map, char_to_cat=None, param_map=None):
    state = DummyState(cs_map=cs_map,
                       param_map=param_map, char_to_cat=char_to_cat)
    instructions = Instructioner.from_string(
        resolve_cs_func=state.router.lookup_control_sequence,
        s=s,
        get_cat_code_func=state.codes.get_cat_code
    )
    return Banisher(instructions, state, instructions.lexer.reader)

def test_resolver():
    cs_map = {
        'hi': ITok(DummyInstructions.test),
    }
    b = string_to_banisher('$hi', cs_map)
    out = b.get_next_output_list()
    assert len(out) == 1 and out[0].matches(cs_map['hi'])

def test_empty_macro():
    cs_map = {
        'macro': make_macro_token(name='macro',
                                  replacement_text=[], parameter_text=[],
                                  parents=None),
    }
    b = string_to_banisher('$macro', cs_map)
    out = b._iterate()
    assert out is None
    assert list(b.instructions.advance_to_end()) == []

def test_short_hand_def():
    cs_map = {
        'cd': ITok(Instructions.count_def),
    }
    b = string_to_banisher('$cd $myBestNumber', cs_map)
    out = b.get_next_output_list()
    assert len(out) == 2
    assert out[0].matches(cs_map['cd'])
    assert out[1].value['name'] == 'myBestNumber'

def test_def():
    cs_map = {
        'df': ITok(Instructions.def_),
    }
    b = string_to_banisher('$df $myName[$sayLola]', cs_map)
    out = b._iterate()
    assert len(out) == 5

def test_let():
    cs_map = {
        'letrill': ITok(Instructions.let),
    }
    b_minimal = string_to_banisher('$letrill $cheese a', cs_map)
    out_minimal = b_minimal._iterate()
    assert len(out_minimal) == 3

    b_equals = string_to_banisher('$letrill $cheese=a', cs_map)
    out_equals = b_equals._iterate()
    assert len(out_equals) == 4

    b_maximal = string_to_banisher('$letrill $cheese= a', cs_map)
    out_maximal = b_maximal._iterate()
    assert len(out_maximal) == 5

def test_toks_def_balanced():
    cs_map = {
        'bestToks': ITok(Instructions.token_parameter),
    }
    b = string_to_banisher('$bestToks [[$this] and $that]', cs_map)
    out = b._iterate()
    # First time, just get first token and set context to wait for balanced
    # text.
    assert len(out) == 1
    # Second time, grab balanced text.
    out = b._iterate()
    assert len(out) == 2
    assert out[-1].instruction == Instructions.balanced_text_and_right_brace
    assert len(out[-1].value) == 9

def test_toks_assign_literal():
    cs_map = {
        'bestToks': ITok(Instructions.token_parameter),
    }
    b = string_to_banisher('$bestToks [[$this] and $that]', cs_map)
    out = b._iterate()
    # First time, just get first token and set context to wait for balanced
    # text.
    assert len(out) == 1
    # Second time, grab balanced text.
    out = b._iterate()
    assert len(out) == 2
    assert out[-1].instruction == Instructions.balanced_text_and_right_brace
    assert len(out[-1].value) == 9

def test_toks_assign_variable():
    cs_map = {
        'bestOfToks': ITok(Instructions.token_parameter),
        'worstOfToks': ITok(Instructions.token_parameter),
    }
    b = string_to_banisher('$bestOfToks $worstOfToks', cs_map)
    out = b._iterate()
    # First time, just get first token and set context to wait for balanced
    # text.
    assert len(out) == 1
    # Second time, grab target toks.
    out = b._iterate()
    assert len(out) == 1
    assert out[-1].instruction == Instructions.token_parameter

def test_expand_after():
    def_target = make_unexpanded_control_sequence_instruction('defTarget',
                                                              parents=None)
    cs_map = {
        'expandAfter': ITok(Instructions.expand_after),
        'defCount': ITok(Instructions.count_def),
        'getTarget': make_macro_token(name='getTarget',
                                      replacement_text=[def_target],
                                      parameter_text=[], parents=None),
    }
    # Should expand $getTarget to [$defTarget], then expand $defCount, which
    # should then read $defTarget as its argument.
    b = string_to_banisher('$expandAfter $defCount $getTarget', cs_map)
    out = b.get_next_output_list()
    assert len(out) == 2
    assert out[0].matches(cs_map['defCount'])
    assert out[1].matches(def_target)

def test_string_control_sequence():
    cs_map = {
        'getString': ITok(Instructions.string),
    }
    param_map = {
        Parameters.escape_char: ord('@'),
    }
    b = string_to_banisher('$getString $CS', cs_map, param_map=param_map)
    out = b.get_next_output_list()
    assert all(t.value['cat'] == CatCode.other for t in out)
    assert ''.join(t.value['char'] for t in out) == '@CS'

def test_string_character():
    cs_map = {
        'getString': ITok(Instructions.string),
    }
    param_map = {
        Parameters.escape_char: ord('@'),
    }
    b = string_to_banisher('$getString A', cs_map, param_map=param_map)
    out = b.get_next_output_list()
    assert all(t.value['cat'] == CatCode.other for t in out)
    assert ''.join(t.value['char'] for t in out) == 'A'

def test_string_control_sequence_containing_space():
    cs_map = {
        'getString': ITok(Instructions.string),
    }
    param_map = {
        Parameters.escape_char: ord('@'),
    }
    char_to_cat_weird = test_char_to_cat.copy()
    char_to_cat_weird[' '] = CatCode.letter

    b = string_to_banisher('$getString$CS WITH SPACES', cs_map,
                           char_to_cat=char_to_cat_weird,
                           param_map=param_map)
    out = b.get_next_output_list()
    for t in out:
        if t.value['char'] == ' ':
            correct_cat = CatCode.space
        else:
            correct_cat = CatCode.other
        assert t.value['cat'] == correct_cat
    assert ''.join(t.value['char'] for t in out) == '@CS WITH SPACES'

def test_string_control_sequence_no_escape():
    cs_map = {
        'getString': ITok(Instructions.string),
    }
    param_map = {
        # Negative value should cause no escape character to be shown.
        Parameters.escape_char: -1,
    }

    b = string_to_banisher('$getString$NoEscapeCS', cs_map,
                           param_map=param_map)
    out = b.get_next_output_list()
    assert all(t.value['cat'] == CatCode.other for t in out)
    assert ''.join(t.value['char'] for t in out) == 'NoEscapeCS'

def test_cs_name():
    char = 'a'
    a_token = char_instr_tok(char, CatCode.letter)
    make_A_token = make_macro_token(name='theA',
                                    replacement_text=[a_token],
                                    parameter_text=[],
                                    parents=None)
    cs_map = {
        'getCSName': ITok(Instructions.cs_name),
        'endCSName': ITok(Instructions.end_cs_name),
        'theA': make_A_token,
    }

    b = string_to_banisher('$getCSName theA$endCSName', cs_map)
    # In the first iteration, should make a $theA control sequence call.
    # In the second iteration, should expand $theA to `a_token`.
    out = b.get_next_output_list()
    assert len(out) == 1
    assert out[0].matches(a_token)

def test_cs_name_end_by_expansion():
    # I seem to have made this test very complicated. The idea is that a macro,
    # $theFThenEnd, makes the string 'theF' then '\endcsname'.
    # This is then procesed by \csname, to produce a control sequence call
    # '$theF'.
    # This control sequence is then expanded to the string 'F'.
    char = 'F'
    F_token = char_instr_tok(char, CatCode.letter)
    cs_name = 'theF'
    the_F_then_end_token = make_macro_token(
        name='theFThenEnd',
        replacement_text=([char_instr_tok(c, CatCode.letter)
                           for c in cs_name] +
                          [ITok(Instructions.end_cs_name)]),
        parameter_text=[],
        parents=None,
    )
    make_F_token = make_macro_token(name='theF',
                                    replacement_text=[F_token],
                                    parameter_text=[],
                                    parents=None)
    cs_map = {
        'getCSName': ITok(Instructions.cs_name),
        'theFThenEnd': the_F_then_end_token,
        'theF': make_F_token,
    }

    b = string_to_banisher('$getCSName $theFThenEnd', cs_map)
    # In the first iteration, should make a $AND control sequence call.
    # In the second iteration, should expand $AND to `a_token`.
    out = b.get_next_output_list()
    assert len(out) == 1
    assert out[0].matches(F_token)

def test_cs_name_containing_non_char():
    cs_map = {
        'getCSName': ITok(Instructions.cs_name),
        'endCSName': ITok(Instructions.end_cs_name),
        'primitive': ITok(DummyInstructions.test),
    }

    b = string_to_banisher('$getCSName $primitive $endCSName', cs_map)
    with pytest.raises(UserError):
        b.get_next_output_list()

def test_change_case():
    B_token = char_instr_tok('B', CatCode.letter)
    make_B_token = make_macro_token(name='makeB', replacement_text=[B_token],
                                    parameter_text=[], parents=None)
    y_token = char_instr_tok('y', CatCode.letter)
    make_y_token = make_macro_token(name='makey', replacement_text=[y_token],
                                    parameter_text=[], parents=None)

    cs_map = {
        'upper': ITok(Instructions.upper_case),
        'lower': ITok(Instructions.lower_case),
        'makeB': make_B_token,
        'makey': make_y_token,
    }

    b = string_to_banisher('$upper[abc]', cs_map)
    out = b.advance_to_end()
    assert ''.join(t.value['char'] for t in out) == 'ABC'

    b = string_to_banisher('$lower[XYZ]', cs_map)
    out = b.advance_to_end()
    assert ''.join(t.value['char'] for t in out) == 'xyz'

    b = string_to_banisher('$lower[A$makeB C]', cs_map)
    out = b.advance_to_end()
    assert ''.join(t.value['char'] for t in out) == 'aBc'

    b = string_to_banisher('$upper[x$makey z]', cs_map)
    out = b.advance_to_end()
    assert ''.join(t.value['char'] for t in out) == 'XyZ'

def test_if():
    cs_map = {
        'ifYes': ITok(Instructions.if_true),
        'ifNo': ITok(Instructions.if_false),
        'else': ITok(Instructions.else_),
        'endIf': ITok(Instructions.end_if),
    }

    b = string_to_banisher('$ifYes abc$else def $endIf', cs_map)
    out = b.advance_to_end()
    assert ''.join(t.value['char'] for t in out) == 'abc'

    b = string_to_banisher('$ifNo abc$else def$endIf', cs_map)
    out = b.advance_to_end()
    assert ''.join(t.value['char'] for t in out) == 'def'

def test_afters():
    cs_map = {
        'assignThen': ITok(Instructions.after_assignment),
        'groupThen': ITok(Instructions.after_group),
    }
    for cs in cs_map:
        b = string_to_banisher(f'${cs} $something', cs_map)
        out = b.get_next_output_list()
        assert len(out) == 2
        assert out[0].matches(cs_map[cs])
        assert out[1].instruction == Instructions.arbitrary_token
        target_tok = out[1].value
        assert target_tok.value['name'] == 'something'

def test_input():
    cs_map = {
        'putIn': ITok(Instructions.input),
    }
    b = string_to_banisher('$putIn tests/test_files/test', cs_map)
    out = list(b.advance_to_end())
    print(out)

def test_integer_tokenize():
    ts = get_token_representation_integer(-23, parents=None)
    assert len(ts) == 3
    assert ts[0].value['char'] == '-' and ts[0].value['cat'] == CatCode.other
    assert ts[1].value['char'] == '2' and ts[0].value['cat'] == CatCode.other
    assert ts[2].value['char'] == '3' and ts[0].value['cat'] == CatCode.other

def test_dimension_tokenize():
    ts = get_token_representation_dimension(pt2sp(-12.2), parents=None)
    assert len(ts) == 7
    assert ''.join(t.value['char'] for t in ts) == '-12.2pt'
    assert all(t.value['cat'] == CatCode.other for t in ts)

# def test_the():
#     cs_map = {
#         'stringify': ITok(Instructions.the),
#         'preTolerance': ITok(Instructions.integer_parameter,
#                              value={'parameter': Parameters.pre_tolerance}),
#     }
#     b = string_to_banisher('$stringify $preTolerance', cs_map)
#     out = list(b.advance_to_end())
#     print(out)


text:
import lombok.Data;
class DataOnLocalClass1 {
  DataOnLocalClass1() {
    super();
  }
  public static void main(String[] args) {
    @Data class Local {
      final int x;
      String name;
      public @java.lang.SuppressWarnings("all") Local(final int x) {
        super();
        this.x = x;
      }
      public @java.lang.SuppressWarnings("all") int getX() {
        return this.x;
      }
      public @java.lang.SuppressWarnings("all") String getName() {
        return this.name;
      }
      public @java.lang.SuppressWarnings("all") void setName(final String name) {
        this.name = name;
      }
      public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
        if ((o == this))
            return true;
        if ((! (o instanceof Local)))
            return false;
        final Local other = (Local) o;
        if ((! other.canEqual((java.lang.Object) this)))
            return false;
        if ((this.getX() != other.getX()))
            return false;
        if (((this.getName() == null) ? (other.getName() != null) : (! this.getName().equals((java.lang.Object) other.getName()))))
            return false;
        return true;
      }
      public @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
        return (other instanceof Local);
      }
      public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = ((result * PRIME) + this.getX());
        result = ((result * PRIME) + ((this.getName() == null) ? 0 : this.getName().hashCode()));
        return result;
      }
      public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
        return (((("Local(x=" + this.getX()) + ", name=") + this.getName()) + ")");
      }
    }
  }
}
class DataOnLocalClass2 {
  {
    @Data class Local {
      @Data class InnerLocal {
        @lombok.NonNull String name;
        public @java.lang.SuppressWarnings("all") InnerLocal(final @lombok.NonNull String name) {
          super();
          if ((name == null))
              throw new java.lang.NullPointerException("name");
          this.name = name;
        }
        public @lombok.NonNull @java.lang.SuppressWarnings("all") String getName() {
          return this.name;
        }
        public @java.lang.SuppressWarnings("all") void setName(final @lombok.NonNull String name) {
          if ((name == null))
              throw new java.lang.NullPointerException("name");
          this.name = name;
        }
        public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
          if ((o == this))
              return true;
          if ((! (o instanceof InnerLocal)))
              return false;
          final InnerLocal other = (InnerLocal) o;
          if ((! other.canEqual((java.lang.Object) this)))
              return false;
          if (((this.getName() == null) ? (other.getName() != null) : (! this.getName().equals((java.lang.Object) other.getName()))))
              return false;
          return true;
        }
        public @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
          return (other instanceof InnerLocal);
        }
        public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
          final int PRIME = 31;
          int result = 1;
          result = ((result * PRIME) + ((this.getName() == null) ? 0 : this.getName().hashCode()));
          return result;
        }
        public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
          return (("Local.InnerLocal(name=" + this.getName()) + ")");
        }
      }
      final int x;
      public @java.lang.SuppressWarnings("all") Local(final int x) {
        super();
        this.x = x;
      }
      public @java.lang.SuppressWarnings("all") int getX() {
        return this.x;
      }
      public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
        if ((o == this))
            return true;
        if ((! (o instanceof Local)))
            return false;
        final Local other = (Local) o;
        if ((! other.canEqual((java.lang.Object) this)))
            return false;
        if ((this.getX() != other.getX()))
            return false;
        return true;
      }
      public @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
        return (other instanceof Local);
      }
      public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = ((result * PRIME) + this.getX());
        return result;
      }
      public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
        return (("Local(x=" + this.getX()) + ")");
      }
    }
  }
  DataOnLocalClass2() {
    super();
  }
}