You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dj...@apache.org on 2007/09/05 23:03:04 UTC

svn commit: r573054 - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe: client/Submitter.java test/OperationsTester.java

Author: djd
Date: Wed Sep  5 14:03:03 2007
New Revision: 573054

URL: http://svn.apache.org/viewvc?rev=573054&view=rev
Log:
Add a class to submit Order Entry business transactions through an Operations class

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/client/Submitter.java   (with props)
Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/test/OperationsTester.java

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/client/Submitter.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/client/Submitter.java?rev=573054&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/client/Submitter.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/client/Submitter.java Wed Sep  5 14:03:03 2007
@@ -0,0 +1,323 @@
+/*
+ *
+ * Derby - Class org.apache.derbyTesting.system.oe.client.Submitter
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, 
+ * software distributed under the License is distributed on an 
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
+ * either express or implied. See the License for the specific 
+ * language governing permissions and limitations under the License.
+ */
+package org.apache.derbyTesting.system.oe.client;
+
+import java.io.PrintStream;
+import java.math.BigDecimal;
+
+import org.apache.derbyTesting.system.oe.util.OERandom;
+
+/**
+ * Class that submits Order Entry transactions
+ * to a database through an instance of an Operations class.
+ * This class is responsible for the mix of transactions
+ * and the generation of the random input values.
+ * 
+ * Sub-classes can override the mix.
+ */
+public class Submitter {
+    
+    /**
+     * Offset of Stock Level transaction in returned
+     * arrays with run information.
+     */
+    public static final int STOCK_LEVEL = 0;
+    /**
+     * Offset of Order Status by Name transaction in returned
+     * arrays with run information.
+     */    
+    public static final int ORDER_STATUS_BY_NAME = 1;
+    /**
+     * Offset of Order Status by Id transaction in returned
+     * arrays with run information.
+     */
+    public static final int ORDER_STATUS_BY_ID = 2;
+    
+     /**
+      * Offset of Payment by Name transaction in returned
+      * arrays with run information.
+      */
+    public static final int PAYMENT_BY_NAME = 3;
+    
+    /**
+     * Offset of Payement by ID transaction in returned
+     * arrays with run information.
+     */
+    public static final int PAYMENT_BY_ID = 4;
+    
+    /**
+     * Offset of Delivery transaction in returned
+     * arrays with run information.
+     */
+    public static final int DELIVERY_SCHEDULE = 5;
+    
+    /**
+     * Offset of New Order transaction in returned
+     * arrays with run information.
+     */
+    public static final int NEW_ORDER = 6;
+    
+    /**
+     * Offset of New Order transaction that rolled back in returned
+     * arrays with run information.
+     */
+    public static final int NEW_ORDER_ROLLBACK = 7;
+    
+    /**
+     * Display to write the output to.
+     */
+    private final Display display;
+    
+    /**
+     * How the business transactions are implemented.
+     */
+    private final Operations ops;
+    
+    /**
+     * My own random number generator.
+     */
+    private final OERandom rand;
+    
+    /**
+     * Scale of the database.
+     */
+    private final short maxW;
+    
+    /**
+     * Record of how many transactions are implemented.
+     */
+    private final int[] transactionCount;
+
+    public Submitter(Display display, Operations ops, OERandom rand,
+            short maxW)
+        throws Exception
+    {
+        this.display = display;
+        this.ops = ops;
+        this.rand = rand;
+        this.maxW = maxW;
+        
+        transactionCount = new int[NEW_ORDER_ROLLBACK+1];
+    }
+    
+    /**
+     * Run an order entry transaction picking the specific
+     * transaction at random with a hard-coded mix.
+     * @param displayData Passed onto Display calls
+     * @throws Exception Error executing the transaction
+     */
+    public void runTransaction(Object displayData) throws Exception
+    {       
+        int chooseType = rand.randomInt(1, 100);
+        
+        int type = mixType(chooseType);
+        
+        switch (type)
+        {
+        case Submitter.DELIVERY_SCHEDULE:
+            runScheduleDelivery(displayData);
+            break;
+        case Submitter.NEW_ORDER:
+            runNewOrder(displayData, false);
+            break;
+        case Submitter.NEW_ORDER_ROLLBACK:
+            runNewOrder(displayData, true);
+            break;
+        case Submitter.ORDER_STATUS_BY_ID:
+            runOrderStatus(displayData, false);
+            break;
+        case Submitter.ORDER_STATUS_BY_NAME:
+            runOrderStatus(displayData, true);
+            break;
+        case Submitter.PAYMENT_BY_ID:
+            runPayment(displayData, false);
+            break;
+        case Submitter.PAYMENT_BY_NAME:
+            runPayment(displayData, true);
+            break;
+        case Submitter.STOCK_LEVEL:
+            runStockLevel(displayData);
+            break;
+        }
+        
+        transactionCount[type]++;
+    }
+    
+    /**
+     * Return one of transaction constants to run that transaction.
+     * This mix in not correct for TPC-C specification.
+     * With the official spec the final mix of transactions
+     * must match a certain profile. With this setup the
+     * mix is fixed upon input following the TPC-C final ratios.
+     * This will give approximately correct results, but the final
+     * mix will not be in line with TPC-C rules. This is because
+     * different transactions have different execution times.
+     * @param chooseType Random number between 1 and 100 inclusive.
+     * @return A transaction constant from this class.
+     */
+    protected int mixType(int chooseType)
+    {
+        if (chooseType <= 43)
+        {
+            boolean byName = rand.randomInt(1, 100) <= 60;
+            return byName ?
+                Submitter.PAYMENT_BY_NAME : Submitter.PAYMENT_BY_ID;       
+        }
+        else if (chooseType <= (43 + 4))
+        {
+            boolean byName = rand.randomInt(1, 100) <= 60;
+            return byName ?
+                Submitter.ORDER_STATUS_BY_NAME : Submitter.ORDER_STATUS_BY_ID;
+        }
+        else if (chooseType <= (43 + 4 + 4))
+            return Submitter.DELIVERY_SCHEDULE;
+        else if (chooseType <= (43 + 4 + 4 + 4))
+            return Submitter.STOCK_LEVEL;
+        else
+        {
+            // 1% rollback
+            boolean rollback = rand.randomInt(1, 100) == 1;
+            return rollback ?
+               Submitter.NEW_ORDER_ROLLBACK : Submitter.NEW_ORDER;
+        }
+    }
+    
+    protected void runNewOrder(Object displayData, boolean forRollback) {
+        // TODO Auto-generated method stub
+    }
+
+    protected void runScheduleDelivery(Object displayData) {
+        // TODO Auto-generated method stub
+    }
+
+    /**
+     * Run a payment transaction with random input values.
+     */
+    protected void runPayment(Object displayData,
+            boolean byName) throws Exception {
+        
+        if (byName)
+        {
+            ops.payment(display, displayData,
+                    warehouse(), rand.district(),
+                    warehouse(), rand.district(),
+                    rand.randomCLast(), rand.payment().toString());
+        }
+        else
+        {
+            ops.payment(display, displayData,
+                warehouse(), rand.district(),
+                warehouse(), rand.district(),
+                rand.NURand1023(), rand.payment().toString());
+        }
+     }
+
+    /**
+     * Return a random warehouse
+     * @return
+     */
+    private final short warehouse() {
+        return (short) rand.randomInt(1, maxW);
+    }
+
+    /**
+     * Run a stock level transaction with random input values.
+     */
+    protected void runStockLevel(Object displayData) throws Exception
+    {
+        ops.stockLevel(display, displayData,
+                warehouse(), rand.district(), rand.threshold());
+    }
+    
+    /**
+     * Run an order status transaction with random input values.
+     */
+    protected void runOrderStatus(Object displayData, boolean byName) throws Exception {
+
+        if (byName)
+        {
+            ops.orderStatus(display, displayData,
+                    warehouse(), rand.district(), rand.randomCLast());
+        }
+        else
+        {
+            ops.orderStatus(display, displayData,
+                warehouse(), rand.district(), rand.NURand1023());
+        }
+
+    }
+    
+    /**
+     * Print a simple report of the activity.
+     * @param out
+     */
+    public void printReport(PrintStream out) {
+             
+        int total = 0;
+        for (int i = 0; i < transactionCount.length; i++)
+            total += transactionCount[i];
+        
+        out.println("Total Transactions: " + total);
+        
+        int noTotal = transactionCount[NEW_ORDER] +
+            transactionCount[NEW_ORDER_ROLLBACK];       
+        int pyCount = transactionCount[PAYMENT_BY_NAME] +
+            transactionCount[PAYMENT_BY_ID];
+        int osCount = transactionCount[ORDER_STATUS_BY_NAME] +
+            transactionCount[ORDER_STATUS_BY_ID];
+
+        out.println(transactionCount("New Order         ", noTotal, total));        
+        out.println(transactionCount("Payment           ",  pyCount, total));
+        out.println(transactionCount("Order Status      ",  osCount, total));
+        out.println(transactionCount("    By Name       ",  transactionCount[ORDER_STATUS_BY_NAME], total));
+        out.println(transactionCount("    By Identifier ",  transactionCount[ORDER_STATUS_BY_ID], total));
+        
+        out.println(transactionCount("Stock Level       ", 
+                transactionCount[STOCK_LEVEL], total));
+        out.println(transactionCount("Schedule Delivery ", 
+                transactionCount[DELIVERY_SCHEDULE], total));
+    }
+    
+    private String transactionCount(String name, int count, int total) 
+    {
+        return name + " : " + percent(count, total) +
+           "(" + count + ")" ;
+        
+    }
+    
+    private String percent(int count, int total)
+    {
+        BigDecimal c = new BigDecimal((long) count * 100L);
+        BigDecimal t = new BigDecimal((long) total);
+        
+        BigDecimal p = c.divide(t, 2, BigDecimal.ROUND_DOWN);
+        
+        return p.toString().concat("%");
+    }
+
+    /**
+     * Get the executed transaction counts.
+     * 
+     * @return
+     */
+    public int[] getTransactionCount() {
+        return transactionCount;
+    }   
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/client/Submitter.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/test/OperationsTester.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/test/OperationsTester.java?rev=573054&r1=573053&r2=573054&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/test/OperationsTester.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/system/oe/test/OperationsTester.java Wed Sep  5 14:03:03 2007
@@ -24,6 +24,7 @@
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.system.oe.client.Display;
 import org.apache.derbyTesting.system.oe.client.Operations;
+import org.apache.derbyTesting.system.oe.client.Submitter;
 import org.apache.derbyTesting.system.oe.direct.Standard;
 import org.apache.derbyTesting.system.oe.model.Customer;
 import org.apache.derbyTesting.system.oe.model.District;
@@ -77,6 +78,9 @@
             
             ops.stockLevel(this, inputData,
                     w, d, threshold);
+            
+            // Ensures the Display object read it.
+            assertTrue(inputData.isEmpty());
         }
     }
     
@@ -101,6 +105,8 @@
             inputData.put("c", new Integer(c));
 
             ops.orderStatus(this, inputData, w, d, c);
+            // Ensures the Display object read it.
+            assertTrue(inputData.isEmpty());
         }
         
         // By name 
@@ -116,6 +122,8 @@
             inputData.put("customerLast", customerLast);
 
             ops.orderStatus(this, inputData, w, d, customerLast);
+            // Ensures the Display object read it.
+            assertTrue(inputData.isEmpty());
             
         }
     }
@@ -181,14 +189,27 @@
     }
 
     public void displayStockLevel(Object displayData, short w, short d, int threshold, int lowStock) throws Exception {
+        
+        // Submitter does not fill this in.
+        if (displayData == null)
+            return;
+        
         HashMap inputData = (HashMap) displayData;
         assertEquals("sl:w", this.w, w);
         assertEquals("sl:d", ((Short) inputData.get("d")).shortValue(), d);
         assertEquals("sl:threshold", ((Integer) inputData.get("threshold")).intValue(), threshold);
-        assertTrue("sl:low stock", lowStock >= 0); 
+        assertTrue("sl:low stock", lowStock >= 0);
+        
+        // Clear it to inform the caller that it was read.
+        inputData.clear();
     }
 
     public void displayOrderStatus(Object displayData, boolean byName, Customer customer, Order order, OrderLine[] lineItems) throws Exception {
+        
+        // Submitter does not fill this in.
+        if (displayData == null)
+            return;
+        
         HashMap inputData = (HashMap) displayData;
         assertEquals("os:w", this.w, customer.getWarehouse());
         assertEquals("os:d", ((Short) inputData.get("d")).shortValue(), customer.getDistrict());
@@ -201,6 +222,9 @@
         {
             assertNull(inputData.get("customerLast"));
         }
+        
+        // Clear it to inform the caller that it was read.
+        inputData.clear();
     }
 
     public void displayPayment(Object displayData, String amount, boolean byName, Warehouse warehouse, District district, Customer customer) throws Exception {
@@ -215,6 +239,28 @@
 
     public void displayScheduleDelivery(Object displayData, short w, short carrier) throws Exception {
         // TODO Auto-generated method stub
+        
+    }
+    
+    public void testSubmitter() throws Exception
+    {
+        Submitter submitter = new Submitter(this, this.ops, this.rand,
+                (short) 1);
+        
+        int tranCount = 37;
+        
+        for (int i = 0; i < tranCount; i++)
+        {
+            submitter.runTransaction(null);
+        }
+        
+        int[] executeCounts = submitter.getTransactionCount();
+        int totalTran = 0;
+        for (int i = 0; i < executeCounts.length; i++)
+            totalTran += executeCounts[i];
+        
+        assertEquals("Mismatch on Submitter transaction count",
+                tranCount, totalTran);
         
     }
 }