/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.jmx.compliance.objectname; import java.util.Hashtable; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Hammer ObjectName, making sure it spots all malformed inputs. * * This may look like overkill but it's not. I want each * permutation to run independantly for full test coverage. * * This suite has twice as many tests (about 60) as my last * testcase - and for that it caught one extra bug for me. * * @todo check we are throwing MalformedObjectNameException and NullPointerException * for the right errors * @author <a href="mailto:trevor@protocool.com">Trevor Squires</a>. */ public class MalformedSUITE extends TestSuite { public static final String GOOD_DOMAIN = "domain"; public static final String GOOD_KEY = "key1"; public static final String GOOD_VALUE = "val1"; // strings containing illegal chars to use in keys public static final String[] BAD_KEYS = { "", // cannot be zero sized "som:thing", // cannot contain domain separator "som?thing", // cannot contain pattern chars "som*thing", // cannot contain pattern chars "som,thing", // cannot contain kvp chunk separator "som=thing", // cannot contain kvp separator "som\nthing", // cannot contain \n separator }; // strings containing illegal chars to use in values public static final String[] BAD_VALS = { "som:thing", // cannot contain domain separator "som?thing", // cannot contain pattern chars "som*thing", // cannot contain pattern chars "som,thing", // cannot contain kvp chunk separator "som=thing", // cannot contain kvp separator "som\nthing", // cannot contain \n separator "som\"thing", // unterminated quote "som\"\\b\"thing", // bad escape inside quote "som\"" + '\n' + "\"thing", // new line inside quote "som\"\"\"thing", // quote inside quote "som\"?\"thing", // question mark inside quote "som\"*\"thing", // asterisk inside quote }; // domains containing illegal domain chars public static final String[] BAD_DOMAINS = { "doma:in", // : char in domain "doma\nin", // \n char in domain }; // pre-cooked name strings dealing with structural malformations public static final String[] BAD_FULLNAMES = { "domain:key=val,key=val2", // duplicate key "domain:=,foo=bar", // both key and value empty "domain:key=val,,foo=bar", // missing kvp in middle "domain:,key=val,foo=bar", // missing kvp at beginning "domain:key=val,foo=bar,", // missing kvp at end "domain:key=val, ,foo=bar", // malformed kvp, no = char "domain:key=val,*,*", // duplicate asterisks "domain:*,key=val,*", // duplicate asterisks "domain:*,key1=val1,*,key2=val2", // duplicate asterisks "domain: *,key1=val1,key2=val2", // asterisk with a leading space "domain:key1=val1,key2=val2, *", // asterisk with a leading space "domain:key1=val1,key2=val2,* ", // asterisk with a trailing space "domain:", // no properties null, // null is not allowed }; public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public static Test suite() { TestSuite suite = new TestSuite("All Malformed Tests"); // Tests for nulls suite.addTest(new DomainKeyValueTEST(null, null, null)); suite.addTest(new DomainKeyValueTEST(null, "key1", "val1")); suite.addTest(new DomainKeyValueTEST("domain", null, "val1")); suite.addTest(new DomainKeyValueTEST("domain", "key1", null)); suite.addTest(new DomainKeyValueTEST("domain", null, null)); suite.addTest(new DomainHashtableTEST(null, "key1", "val1")); // extra stuff related to null or zero sized hashtable suite.addTestSuite(DomainHashtableExtraTEST.class); // all illegal domain characters for (int i = 0; i < BAD_DOMAINS.length; i++) { suite.addTest(new FullNameTEST(BAD_DOMAINS[i] + ":" + GOOD_KEY + "=" + GOOD_VALUE)); suite.addTest(new DomainKeyValueTEST(BAD_DOMAINS[i], GOOD_KEY, GOOD_VALUE)); suite.addTest(new DomainHashtableTEST(BAD_DOMAINS[i], GOOD_KEY, GOOD_VALUE)); } // all illegal key characters for (int i = 0; i < BAD_KEYS.length; i++) { suite.addTest(new FullNameTEST(GOOD_DOMAIN + ":" + BAD_KEYS[i] + "=" + GOOD_VALUE)); suite.addTest(new DomainKeyValueTEST(GOOD_DOMAIN, BAD_KEYS[i], GOOD_VALUE)); suite.addTest(new DomainHashtableTEST(GOOD_DOMAIN, BAD_KEYS[i], GOOD_VALUE)); } // all illegal value characters for (int i = 0; i < BAD_VALS.length; i++) { suite.addTest(new FullNameTEST(GOOD_DOMAIN + ":" + GOOD_KEY + "=" + BAD_VALS[i])); suite.addTest(new DomainKeyValueTEST(GOOD_DOMAIN, GOOD_KEY, BAD_VALS[i])); suite.addTest(new DomainHashtableTEST(GOOD_DOMAIN, GOOD_KEY, BAD_VALS[i])); } // all the structurally malformed fullnames for (int i = 0; i < BAD_FULLNAMES.length; i++) { suite.addTest( new FullNameTEST(BAD_FULLNAMES[i])); } return suite; } public static class FullNameTEST extends TestCase { private String fullName; public FullNameTEST(String fullName) { super("testMalformed"); this.fullName = fullName; } public void testMalformed() { boolean caught = false; try { new ObjectName(fullName); } catch (MalformedObjectNameException e) { caught = true; } catch (NullPointerException e) { caught = true; if (fullName != null) fail("Unexpected NullPointerException for " + fullName); } if (caught == false) { if (fullName != null) if (fullName.equals("domain:=val1") || fullName.equals("domain:=,foo=bar")) fail("FAILS IN RI: expected a MalformedObjectNameException for: " + fullName); fail("expected a MalformedObjectNameException for: " + fullName); } caught = false; try { ObjectName.getInstance(fullName); } catch (MalformedObjectNameException e) { caught = true; } catch (NullPointerException e) { caught = true; if (fullName != null) fail("Unexpected NullPointerException for " + fullName); } if (caught == false) { if (fullName != null) if (fullName.equals("domain:=val1") || fullName.equals("domain:=,foo=bar")) fail("FAILS IN RI: expected a MalformedObjectNameException for: " + fullName); fail("expected a MalformedObjectNameException for: " + fullName); } } } public static class DomainKeyValueTEST extends TestCase { private String domain; private String key; private String value; public DomainKeyValueTEST(String domain, String key, String value) { super("testMalformed"); this.domain = domain; this.key = key; this.value = value; } public void testMalformed() { boolean caught = false; try { new ObjectName(domain, key, value); } catch (MalformedObjectNameException e) { caught = true; } catch (NullPointerException e) { caught = true; if (domain != null && key != null && value != null) fail("Unexpected NullPointerException for " + domain + ":" + key + "=" + value); } if (caught == false) { if (value != null) if (value.equals("som\"thing") || value.equals("som\"\\b\"thing") || value.equals("som\"\"\"thing")) fail("FAILS IN RI: expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); fail("expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); } caught = false; try { ObjectName.getInstance(domain, key, value); } catch (MalformedObjectNameException e) { caught = true; } catch (NullPointerException e) { caught = true; if (domain != null && key != null && value != null) fail("Unexpected NullPointerException for " + domain + ":" + key + "=" + value); } if (caught == false) { if (value != null) if (value.equals("som\"thing") || value.equals("som\"\\b\"thing") || value.equals("som\"\"\"thing")) fail("FAILS IN RI: expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); fail("expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); } } } public static class DomainHashtableTEST extends TestCase { private String domain; private String key; private String value; public DomainHashtableTEST(String domain, String key, String value) { super("testMalformed"); this.domain = domain; this.key = key; this.value = value; } public void testMalformed() { boolean caught = false; try { Hashtable h = new Hashtable(); h.put(key, value); new ObjectName(domain, h); } catch (MalformedObjectNameException e) { caught = true; } catch (NullPointerException e) { caught = true; if (domain != null && key != null && value != null) fail("Unexpected NullPointerException for " + domain + ":" + key + "=" + value); } if (caught == false) { if (value != null) if (value.equals("som\"thing") || value.equals("som\"\\b\"thing") || value.equals("som\"\"\"thing")) fail("FAILS IN RI: expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); fail("expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); } caught = false; try { Hashtable h = new Hashtable(); h.put(key, value); ObjectName.getInstance(domain, h); } catch (MalformedObjectNameException e) { caught = true; } catch (NullPointerException e) { caught = true; if (domain != null && key != null && value != null) fail("Unexpected NullPointerException for " + domain + ":" + key + "=" + value); } if (caught == false) { if (value != null) if (value.equals("som\"thing") || value.equals("som\"\\b\"thing") || value.equals("som\"\"\"thing")) fail("FAILS IN RI: expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); fail("expected a MalformedObjectNameException for: " + domain + ":" + key + "=" + value); } } } public static class DomainHashtableExtraTEST extends TestCase { public DomainHashtableExtraTEST(String s) { super(s); } public void testNullDomain() { Hashtable h = new Hashtable(); h.put(new Object(), GOOD_VALUE); doCheck(null, h, "<null domain>", true); } public void testNullHashtable() { doCheck(GOOD_DOMAIN, null, "<null hashtable>", true); } public void testEmptyHashtable() { doCheck(GOOD_DOMAIN, new Hashtable(), "<empty_hashtable>", false); } public void testNonStringKey() { Hashtable h = new Hashtable(); h.put(new Object(), GOOD_VALUE); doCheck(GOOD_DOMAIN, h, "<non_string_key>=" + GOOD_VALUE, false); } public void testNonStringValue() { Hashtable h = new Hashtable(); h.put(GOOD_KEY, new Object()); doCheck(GOOD_DOMAIN, h, GOOD_KEY + "=<non_string_value>", false); } private void doCheck(String domain, Hashtable h, String failureHint, boolean expectNull) { boolean caught = true; try { new ObjectName(domain, h); } catch (MalformedObjectNameException e) { caught = true; if (expectNull) fail("FAILS IN RI: Expected a NullPointerException for: " + domain + ":" + failureHint); } catch (NullPointerException e) { if (expectNull == false) fail("unexpected a NullPointerException for: " + domain + ":" + failureHint); } if (caught == false) fail("expected a MalformedObjectNameException for: " + domain + ":" + failureHint); caught = true; try { ObjectName.getInstance(domain, h); } catch (MalformedObjectNameException e) { caught = true; if (expectNull) fail("FAILS IN RI: Expected a NullPointerException for: " + domain + ":" + failureHint); } catch (NullPointerException e) { if (expectNull == false) fail("unexpected a NullPointerException for: " + domain + ":" + failureHint); } if (caught == false) fail("expected a MalformedObjectNameException for: " + domain + ":" + failureHint); } } }