/* * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package com.sun.javame.sensor; import com.sun.javame.sensor.helper.SensorUrlGenerator; import com.sun.midp.i3test.TestCase; import javax.microedition.sensor.*; public class TestSensorUrl extends TestCase { /* Correct URLs */ private static final String URL_1 = "sensor:temperature"; private static final String URL_2 = "sensor:temperature;contextType=user"; private static final String URL_3 = "sensor:temperature;contextType=user;model=coolSensor"; private static final String URL_4 = "sensor:temperature;contextType=user;model=coolSensor;location=kitchen"; private static final String URL_5 = "sensor:temperature;model=coolSensor;location=kitchen"; private static final String URL_6 = "sensor:temperature;contextType=user;location=kitchen"; private static final String URL_7 = "sensor:temperature;contextType=user;model=coolSensor"; private static final String URL_8 = "sensor:temperature;model=coolSensor"; /* Incorrect URLs */ private static final String[] URL_INCORRECT = { "wrong_scheme:", "sensor:-no_quantity", "sensor:quantity-no_separator", "sensor:quantity;", // no header after separator "sensor:quantity;wrong", // wrong header after separator "sensor:quantity;contextType+", // no "=" after content type "sensor:quantity;contextType=wrong", // wrong content type value "sensor:quantity;contextType="+SensorInfo.CONTEXT_TYPE_AMBIENT + ";contextType="+SensorInfo.CONTEXT_TYPE_DEVICE, // double content type def "sensor:quantity;model+", // no "=" after model "sensor:quantity;model=one;model=two", // double module def "sensor:quantity;location+", // no "=" after location "sensor:quantity;location=one;location=two" // double location def }; /* Correct URLs */ private static final String[] URL_CORRECT = { "sensor:quantity", // no parameters "sensor:quantity;contextType="+SensorInfo.CONTEXT_TYPE_AMBIENT, // valid content type "sensor:quantity;contextType="+SensorInfo.CONTEXT_TYPE_DEVICE, // valid content type "sensor:quantity;contextType="+SensorInfo.CONTEXT_TYPE_USER, // valid content type "sensor:quantity;model=mod1", // valid model "sensor:quantity;location=loc1", // valid location "sensor:quantity;contextType="+SensorInfo.CONTEXT_TYPE_AMBIENT+ ";model=mod1", // content type + model "sensor:quantity;contextType="+SensorInfo.CONTEXT_TYPE_AMBIENT+ ";location=loc1", // content type + location "sensor:quantity;model=mod1;location=loc1", // model + location "sensor:quantity;contextType="+SensorInfo.CONTEXT_TYPE_AMBIENT+ ";model=mod1;location=loc1", // content type + model + location "sensor:temperature;model=", "sensor:body_fat_percentage;model=1Gf2e427b7nS28F;location=" }; /* Push parameters incorrect */ private static final String[] URL_PUSH_INCORRECT = { "+", // wrong separator (not "?") "?nochannel", // no "channel=..." "?channel+", // no "=" after channel "?channel=+", // wrong channel id "?channel=channel1&channel&limit=5.3&op=eq", // no condition list "?channel=channel1+aaa", // no separator after channel id "?channel=channel1&wrong", // neither "limit" nor "lowerLimit" "?channel=channel1&limit+", // no "=" after limit "?channel=channel1&limit=ud&op=eq", // no number after "limit=" "?channel=channel1&limit=.&op=eq", // wrong number format "?channel=channel1&limit=-&op=eq", // wrong number format "?channel=channel1&limit=5-&op=eq", // wrong number format "?channel=channel1&limit=-.&op=eq", // wrong number format "?channel=channel1&limit=6.5.4&op=eq", // wrong number format "?channel=channel1&limit=5.3&ua=eq", // no "op" "?channel=channel1&limit=5.3&op.eq", // no "=" after "op" "?channel=channel1&limit=5.3&op=wrong", // wrong op value "?channel=channel1&lowerLimit+", // no "=" after "lowerLimit" "?channel=channel1&lowerLimit=aaa", // no number after "lowerLimit" "?channel=channel1&lowerLimit=4.67+", // no separator "?channel=channel1&lowerLimit=4.67&lowerOp+", // no "=" after "lowerOp" "?channel=channel1&lowerLimit=4.67&lowerOp=wrong", // wrong lowerOp value "?channel=channel1&lowerLimit=4.67&lowerOp=ge+", // no separator "?channel=channel1&lowerLimit=4.67&lowerOp=ge&wrong", // no upperLimit "?channel=channel1&lowerLimit=4.67&lowerOp=ge&upperLimit+", // no "=" after "upperLimit" "?channel=channel1&lowerLimit=4.67&lowerOp=ge&upperLimit=wrong", // no number "?channel=channel1&lowerLimit=4.67&lowerOp=ge&upperLimit=-56+", // no separator "?channel=channel1&lowerLimit=4.67&lowerOp=ge&upperLimit=-56&wrong", // no upperOp "?channel=channel1&lowerLimit=4.67&lowerOp=ge&upperLimit=-56&upperOp=wrong" // upperOp wrong value }; /* Push parameters correct */ private static final String[] URL_PUSH_CORRECT = { "?channel=channel1&limit=5.3&op=eq", "?channel=channel1&limit=5.3&op=lt", "?channel=channel1&limit=5.3&op=le", "?channel=channel1&limit=5.3&op=ge", "?channel=channel1&limit=5.3&op=gt", "?channel=channel1&limit=5.3&op=eq&limit=5.3&op=eq", "?channel=channel1&lowerLimit=-4.67&lowerOp=ge&upperLimit=56&upperOp=lt", "?channel=channel1&lowerLimit=-4.67&lowerOp=ge&upperLimit=56&upperOp=lt&limit=5.3&op=eq", "?channel=channel1&limit=5.3&op=eq&channel=channel1&limit=5.3&op=eq", "?channel=channel1&limit=5.3&op=eq&lowerLimit=-4.67&lowerOp=ge&upperLimit=56&upperOp=lt&channel=channel1&limit=5.3&op=eq" }; private void testCorrectURLs() { try { SensorUrl su = SensorUrl.parseUrl(URL_1); assertTrue(su.getQuantity().equals("temperature")); su = SensorUrl.parseUrl(URL_2); assertTrue(su.getQuantity().equals("temperature")); assertTrue(su.getContextType().equals("user")); su = SensorUrl.parseUrl(URL_3); assertTrue(su.getQuantity().equals("temperature")); assertTrue(su.getContextType().equals("user")); assertTrue(su.getModel().equals("coolSensor")); su = SensorUrl.parseUrl(URL_4); assertTrue(su.getQuantity().equals("temperature")); assertTrue(su.getContextType().equals("user")); assertTrue(su.getModel().equals("coolSensor")); assertTrue(su.getLocation().equals("kitchen")); su = SensorUrl.parseUrl(URL_5); assertTrue(su.getQuantity().equals("temperature")); assertTrue(su.getContextType() == null); assertTrue(su.getModel().equals("coolSensor")); assertTrue(su.getLocation().equals("kitchen")); su = SensorUrl.parseUrl(URL_6); assertTrue(su.getQuantity().equals("temperature")); assertTrue(su.getContextType().equals("user")); assertTrue(su.getModel() == null); assertTrue(su.getLocation().equals("kitchen")); su = SensorUrl.parseUrl(URL_7); assertTrue(su.getQuantity().equals("temperature")); assertTrue(su.getContextType().equals("user")); assertTrue(su.getModel().equals("coolSensor")); assertTrue(su.getLocation() == null); su = SensorUrl.parseUrl(URL_8); assertTrue(su.getQuantity().equals("temperature")); assertTrue(su.getContextType() == null); assertTrue(su.getModel().equals("coolSensor")); assertTrue(su.getLocation() == null); } catch (Exception exc) { exc.printStackTrace(); } } private void testCorrectURLs1() { for (int i = 0; i < URL_CORRECT.length; i++) { try { SensorUrl.parseUrl(URL_CORRECT[i]); assertTrue(true); } catch (Exception ex) { assertFalse(true); } } } private void testIncorrectURLs() { for (int i = 0; i < URL_INCORRECT.length; i++) { try { SensorUrl.parseUrl(URL_INCORRECT[i]); assertFalse(true); } catch (IllegalArgumentException e) { assertTrue(true); } catch (Exception ex) { assertFalse(true); } } } private void testIncorrectPushURLs() { for (int i = 0; i < URL_CORRECT.length; i++) { for (int j = 0; j < URL_PUSH_INCORRECT.length; j++) { try { SensorUrl.parseUrlPush(URL_CORRECT[i]+URL_PUSH_INCORRECT[j]); assertFalse(true); } catch (IllegalArgumentException e) { assertTrue(true); } catch (Exception ex) { assertFalse(true); } } } } private void testCorrectPushURLs() { for (int i = 0; i < URL_CORRECT.length; i++) { for (int j = 0; j < URL_PUSH_CORRECT.length; j++) { try { SensorUrl.parseUrlPush(URL_CORRECT[i]+URL_PUSH_CORRECT[j]); assertTrue(true); } catch (Exception ex) { ex.printStackTrace(); assertFalse(true); } } } } private void testGeneratedUrl() { assertTrue(true); for (int i = 0; i < 100000; i++) { String url = SensorUrlGenerator.generateSensorUrl(); try { SensorUrl.parseUrl(url); } catch (IllegalArgumentException e) { System.out.println("Parse failed: " + url); throw e; } } } private void testMultithreadedParsingUrl(final int threadsCount) throws InterruptedException { assertTrue(true); Thread[] threads = new Thread[threadsCount]; final CountDownLatch startupLatch = new CountDownLatch(1); final CountDownLatch endLatch = new CountDownLatch(threadsCount); for (int i = 0; i < threadsCount; i++) { threads[i] = new Thread() { public void run() { try { String url = SensorUrlGenerator.generateSensorUrl(); SensorUrl sensorUrl = null; startupLatch.await(); try { sensorUrl = SensorUrl.parseUrl(url); assertEquals("Source and parsed URL must be equal", url, urlToString(sensorUrl)); } catch (IllegalArgumentException e) { System.out.println("Parse failed: " + url); } } catch (InterruptedException e) { e.printStackTrace(); } finally { endLatch.countDown(); } } }; threads[i].start(); } startupLatch.countDown(); if (!endLatch.await(10000)) { fail("Timed out"); } } public void runTests() { try { declare("testCorrectURLs"); testCorrectURLs(); declare("testCorrectURLs1"); testCorrectURLs1(); declare("testIncorrectURLs"); testIncorrectURLs(); declare("testIncorrectPushURLs"); testIncorrectPushURLs(); declare("testCorrectPushURLs"); testCorrectPushURLs(); declare("testGeneratedUrl"); testGeneratedUrl(); declare("testMultithreadedParsingUrl: 10 threads"); testMultithreadedParsingUrl(10); declare("testMultithreadedParsingUrl: 100 threads"); testMultithreadedParsingUrl(100); declare("testMultithreadedParsingUrl: 500 threads"); testMultithreadedParsingUrl(500); } catch (Throwable t) { fail("" + t); } } private String urlToString(SensorUrl sensorUrl) { StringBuffer sb = new StringBuffer(); sb.append("sensor:"); sb.append(sensorUrl.getQuantity()); if (sensorUrl.getContextType() != null) { sb.append(";contextType="); sb.append(sensorUrl.getContextType()); } if (sensorUrl.getModel() != null) { sb.append(";model="); sb.append(sensorUrl.getModel()); } if (sensorUrl.getLocation() != null) { sb.append(";location="); sb.append(sensorUrl.getLocation()); } return sb.toString(); } } class CountDownLatch { private int count; public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.count = count; } public void await() throws InterruptedException { synchronized(this) { while (count > 0) wait(); } } public boolean await(long timeout) throws InterruptedException { synchronized (this) { if (count <= 0) { return true; } else if (timeout <= 0) { return false; } else { long deadline = System.currentTimeMillis() + timeout; for (;;) { wait(timeout); if (count <= 0) { return true; } else { timeout = deadline - System.currentTimeMillis(); if (timeout <= 0) { return false; } } } } } } public synchronized void countDown() { if (count == 0) return; if (--count == 0) notifyAll(); } public long getCount() { return count; } public String toString() { return super.toString() + "[Count = " + getCount() + "]"; } }