Coverage Report - kg.apc.jmeter.threads.UltimateThreadGroup
 
Classes in this File Line Coverage Branch Coverage Complexity
UltimateThreadGroup
95%
84/88
84%
22/26
2.636
 
 1  
 package kg.apc.jmeter.threads;
 2  
 
 3  
 import kg.apc.jmeter.JMeterPluginsUtils;
 4  
 import org.apache.jmeter.gui.util.PowerTableModel;
 5  
 import org.apache.jmeter.testelement.TestStateListener;
 6  
 import org.apache.jmeter.testelement.property.CollectionProperty;
 7  
 import org.apache.jmeter.testelement.property.JMeterProperty;
 8  
 import org.apache.jmeter.testelement.property.NullProperty;
 9  
 import org.apache.jmeter.testelement.property.PropertyIterator;
 10  
 import org.apache.jmeter.threads.JMeterThread;
 11  
 import org.apache.jmeter.util.JMeterUtils;
 12  
 import org.apache.jorphan.logging.LoggingManager;
 13  
 import org.apache.log.Logger;
 14  
 
 15  
 import java.io.Serializable;
 16  
 import java.util.ArrayList;
 17  
 import java.util.List;
 18  
 
 19  
 public class UltimateThreadGroup
 20  
         extends AbstractSimpleThreadGroup
 21  
         implements Serializable, TestStateListener {
 22  
 
 23  1
     private static final Logger log = LoggingManager.getLoggerForClass();
 24  
 
 25  
     public static final String DATA_PROPERTY = "ultimatethreadgroupdata";
 26  
     public static final String EXTERNAL_DATA_PROPERTY = "threads_schedule";
 27  
 
 28  
     public static final int START_THREADS_CNT_FIELD_NO = 0;
 29  
     public static final int INIT_DELAY_FIELD_NO = 1;
 30  
     public static final int STARTUP_TIME_FIELD_NO = 2;
 31  
     public static final int HOLD_LOAD_FOR_FIELD_NO = 3;
 32  
     public static final int SHUTDOWN_TIME_FIELD_NO = 4;
 33  
 
 34  
     private PropertyIterator scheduleIT;
 35  
     private int threadsToSchedule;
 36  
     private CollectionProperty currentRecord;
 37  
 
 38  
     public UltimateThreadGroup() {
 39  21
         super();
 40  21
     }
 41  
 
 42  
     @Override
 43  
     protected void scheduleThread(JMeterThread thread, long tgStartTime) {
 44  46
         log.debug("Scheduling thread: " + thread.getThreadName());
 45  46
         if (threadsToSchedule < 1) {
 46  10
             if (!scheduleIT.hasNext()) {
 47  0
                 throw new RuntimeException("Not enough schedule records for thread #" + thread.getThreadName());
 48  
             }
 49  
 
 50  10
             currentRecord = (CollectionProperty) scheduleIT.next();
 51  10
             threadsToSchedule = currentRecord.get(0).getIntValue();
 52  
         }
 53  
 
 54  46
         int numThreads = currentRecord.get(START_THREADS_CNT_FIELD_NO).getIntValue();
 55  46
         int initialDelay = currentRecord.get(INIT_DELAY_FIELD_NO).getIntValue();
 56  46
         int startRampUp = currentRecord.get(STARTUP_TIME_FIELD_NO).getIntValue();
 57  46
         int flightTime = currentRecord.get(HOLD_LOAD_FOR_FIELD_NO).getIntValue();
 58  46
         int endRampUp = currentRecord.get(SHUTDOWN_TIME_FIELD_NO).getIntValue();
 59  
 
 60  46
         long ascentPoint = tgStartTime + 1000 * initialDelay;
 61  46
         final int rampUpDelayForThread = (int) Math.floor(1000 * startRampUp * (double) threadsToSchedule / numThreads);
 62  46
         long startTime = ascentPoint + rampUpDelayForThread;
 63  46
         long descentPoint = startTime + 1000 * flightTime + 1000 * startRampUp - rampUpDelayForThread;
 64  
 
 65  46
         thread.setStartTime(startTime);
 66  46
         thread.setEndTime(descentPoint + (int) Math.floor(1000 * endRampUp * (double) threadsToSchedule / numThreads));
 67  
 
 68  46
         thread.setScheduled(true);
 69  46
         threadsToSchedule--;
 70  46
     }
 71  
 
 72  
     public JMeterProperty getData() {
 73  63
         JMeterProperty brokenProp = getProperty(EXTERNAL_DATA_PROPERTY);
 74  63
         JMeterProperty usualProp = getProperty(DATA_PROPERTY);
 75  
 
 76  63
         if (brokenProp instanceof CollectionProperty) {
 77  2
             if (usualProp == null || usualProp instanceof NullProperty) {
 78  1
                 log.warn("Copying '" + EXTERNAL_DATA_PROPERTY + "' into '" + DATA_PROPERTY + "'");
 79  1
                 JMeterProperty newProp = brokenProp.clone();
 80  1
                 newProp.setName(DATA_PROPERTY);
 81  1
                 setProperty(newProp);
 82  
             }
 83  2
             log.warn("Removing property '" + EXTERNAL_DATA_PROPERTY + "' as invalid");
 84  2
             removeProperty(EXTERNAL_DATA_PROPERTY);
 85  
         }
 86  
 
 87  
         //log.info("getData: "+getProperty(DATA_PROPERTY));
 88  63
         CollectionProperty overrideProp = getLoadFromExternalProperty();
 89  63
         if (overrideProp != null) {
 90  1
             return overrideProp;
 91  
         }
 92  
 
 93  62
         return getProperty(DATA_PROPERTY);
 94  
     }
 95  
 
 96  
     public void setData(CollectionProperty rows) {
 97  
         //log.info("setData");
 98  13
         setProperty(rows);
 99  13
     }
 100  
 
 101  
 
 102  
     private CollectionProperty getLoadFromExternalProperty() {
 103  63
         String loadProp = JMeterUtils.getProperty(EXTERNAL_DATA_PROPERTY);
 104  63
         log.debug("Profile prop: " + loadProp);
 105  63
         if (loadProp != null && loadProp.length() > 0) {
 106  
             //expected format : threads_schedule="spawn(1,1s,1s,1s,1s) spawn(2,1s,3s,1s,2s)"
 107  1
             log.info("GUI threads profile will be ignored");
 108  1
             PowerTableModel dataModel = new PowerTableModel(UltimateThreadGroupGui.columnIdentifiers, UltimateThreadGroupGui.columnClasses);
 109  1
             String[] chunks = loadProp.split("\\)");
 110  
 
 111  3
             for (String chunk : chunks) {
 112  
                 try {
 113  2
                     parseChunk(chunk, dataModel);
 114  0
                 } catch (RuntimeException e) {
 115  0
                     log.warn("Wrong  chunk ignored: " + chunk, e);
 116  2
                 }
 117  
             }
 118  
 
 119  1
             log.info("Setting threads profile from property " + EXTERNAL_DATA_PROPERTY + ": " + loadProp);
 120  1
             return JMeterPluginsUtils.tableModelRowsToCollectionProperty(dataModel, UltimateThreadGroup.DATA_PROPERTY);
 121  
         }
 122  62
         return null;
 123  
     }
 124  
 
 125  
     private static void parseChunk(String chunk, PowerTableModel model) {
 126  2
         log.debug("Parsing chunk: " + chunk);
 127  2
         String[] parts = chunk.split("[(,]");
 128  2
         String loadVar = parts[0].trim();
 129  
 
 130  2
         if (loadVar.equalsIgnoreCase("spawn")) {
 131  2
             Integer[] row = new Integer[5];
 132  2
             row[START_THREADS_CNT_FIELD_NO] = Integer.parseInt(parts[1].trim());
 133  2
             row[INIT_DELAY_FIELD_NO] = JMeterPluginsUtils.getSecondsForShortString(parts[2]);
 134  2
             row[STARTUP_TIME_FIELD_NO] = JMeterPluginsUtils.getSecondsForShortString(parts[3]);
 135  2
             row[HOLD_LOAD_FOR_FIELD_NO] = JMeterPluginsUtils.getSecondsForShortString(parts[4]);
 136  2
             row[SHUTDOWN_TIME_FIELD_NO] = JMeterPluginsUtils.getSecondsForShortString(parts[5]);
 137  2
             model.addRow(row);
 138  2
         } else {
 139  0
             throw new RuntimeException("Unknown load type: " + parts[0]);
 140  
         }
 141  2
     }
 142  
 
 143  
     @Override
 144  
     public int getNumThreads() {
 145  42
         int result = 0;
 146  
 
 147  42
         JMeterProperty threadValues = getData();
 148  42
         if (!(threadValues instanceof NullProperty)) {
 149  42
             CollectionProperty columns = (CollectionProperty) threadValues;
 150  42
             List<?> rows = (List<?>) columns.getObjectValue();
 151  42
             for (Object row1 : rows) {
 152  102
                 CollectionProperty prop = (CollectionProperty) row1;
 153  102
                 ArrayList<JMeterProperty> row = (ArrayList<JMeterProperty>) prop.getObjectValue();
 154  
                 //log.info(prop.getStringValue());
 155  102
                 result += row.get(0).getIntValue();
 156  102
             }
 157  
         }
 158  
 
 159  42
         return result;
 160  
     }
 161  
 
 162  
     @Override
 163  
     public void testStarted() {
 164  15
         JMeterProperty data = getData();
 165  15
         if (!(data instanceof NullProperty)) {
 166  13
             scheduleIT = ((CollectionProperty) data).iterator();
 167  
         }
 168  15
         threadsToSchedule = 0;
 169  15
     }
 170  
 
 171  
     @Override
 172  
     public void testStarted(String host) {
 173  1
         testStarted();
 174  1
     }
 175  
 
 176  
     @Override
 177  
     public void testEnded() {
 178  2
     }
 179  
 
 180  
     @Override
 181  
     public void testEnded(String host) {
 182  1
         testEnded();
 183  1
     }
 184  
 
 185  
 
 186  
 }