1 /*
   2  * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package test.rowset;
  24 
  25 import java.io.InputStream;
  26 import java.io.Reader;
  27 import java.io.StringBufferInputStream;
  28 import java.io.StringReader;
  29 import java.math.BigDecimal;
  30 import java.sql.Array;
  31 import java.sql.Blob;
  32 import java.sql.Clob;
  33 import java.sql.Date;
  34 import java.sql.Ref;
  35 import java.sql.SQLException;
  36 import java.sql.Time;
  37 import java.sql.Timestamp;
  38 import java.sql.Types;
  39 import java.time.LocalDate;
  40 import java.time.LocalDateTime;
  41 import java.time.LocalTime;
  42 import java.util.Calendar;
  43 import javax.sql.RowSet;
  44 import javax.sql.rowset.serial.SerialArray;
  45 import javax.sql.rowset.serial.SerialBlob;
  46 import javax.sql.rowset.serial.SerialClob;
  47 import javax.sql.rowset.serial.SerialRef;
  48 import static org.testng.Assert.*;
  49 import org.testng.annotations.DataProvider;
  50 import org.testng.annotations.Test;
  51 import util.StubArray;
  52 import util.StubBaseRowSet;
  53 import util.StubBlob;
  54 import util.StubClob;
  55 import util.StubRef;
  56 import util.TestRowSetListener;
  57 
  58 public class BaseRowSetTests extends CommonRowSetTests {
  59 
  60     private StubBaseRowSet brs;
  61 
  62     @Override
  63     protected RowSet newInstance() throws SQLException {
  64         return new StubBaseRowSet();
  65     }
  66 
  67     /*
  68      * Create a RowSetListener and validate that notifyCursorMoved is called
  69      */
  70     @Test(dataProvider = "rowSetType")
  71     public void baseRowSetTest0000(StubBaseRowSet rs) throws Exception {
  72         TestRowSetListener rsl = new TestRowSetListener();
  73         rs.addRowSetListener(rsl);
  74         rs.notifyCursorMoved();
  75         assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
  76     }
  77 
  78     /*
  79      * Create a RowSetListener and validate that notifyRowChanged is called
  80      */
  81     @Test(dataProvider = "rowSetType")
  82     public void baseRowSetTest0001(StubBaseRowSet rs) throws Exception {
  83         TestRowSetListener rsl = new TestRowSetListener();
  84         rs.addRowSetListener(rsl);
  85         rs.notifyRowChanged();
  86         assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
  87     }
  88 
  89     /*
  90      * Create a RowSetListener and validate that notifyRowSetChanged is called
  91      */
  92     @Test(dataProvider = "rowSetType")
  93     public void baseRowSetTest0002(StubBaseRowSet rs) throws Exception {
  94         TestRowSetListener rsl = new TestRowSetListener();
  95         rs.addRowSetListener(rsl);
  96         rs.notifyRowSetChanged();
  97         assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
  98     }
  99 
 100     /*
 101      * Create multiple RowSetListeners and validate that notifyRowSetChanged
 102      * is called on all listeners
 103      */
 104     @Test(dataProvider = "rowSetType")
 105     public void baseRowSetTest0003(StubBaseRowSet rs) throws Exception {
 106         TestRowSetListener rsl = new TestRowSetListener();
 107         TestRowSetListener rsl2 = new TestRowSetListener();
 108         rs.addRowSetListener(rsl);
 109         rs.addRowSetListener(rsl2);
 110         rs.notifyRowSetChanged();
 111         assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
 112         assertTrue(rsl2.isNotified(TestRowSetListener.ROWSET_CHANGED));
 113     }
 114 
 115     /*
 116      * Create multiple RowSetListeners and validate that notifyRowChanged
 117      * is called on all listeners
 118      */
 119     @Test(dataProvider = "rowSetType")
 120     public void baseRowSetTest0004(StubBaseRowSet rs) throws Exception {
 121         TestRowSetListener rsl = new TestRowSetListener();
 122         TestRowSetListener rsl2 = new TestRowSetListener();
 123         rs.addRowSetListener(rsl);
 124         rs.addRowSetListener(rsl2);
 125         rs.notifyRowChanged();
 126         assertTrue(rsl.isNotified(TestRowSetListener.ROW_CHANGED));
 127         assertTrue(rsl2.isNotified(TestRowSetListener.ROW_CHANGED));
 128     }
 129 
 130     /*
 131      * Create multiple RowSetListeners and validate that notifyCursorMoved
 132      * is called on all listeners
 133      */
 134     @Test(dataProvider = "rowSetType")
 135     public void baseRowSetTest0005(StubBaseRowSet rs) throws Exception {
 136         TestRowSetListener rsl = new TestRowSetListener();
 137         TestRowSetListener rsl2 = new TestRowSetListener();
 138         rs.addRowSetListener(rsl);
 139         rs.addRowSetListener(rsl2);
 140         rs.notifyCursorMoved();
 141         assertTrue(rsl.isNotified(TestRowSetListener.CURSOR_MOVED));
 142         assertTrue(rsl2.isNotified(TestRowSetListener.CURSOR_MOVED));
 143     }
 144 
 145     /*
 146      * Create a RowSetListener and validate that notifyRowSetChanged,
 147      * notifyRowChanged() and notifyCursorMoved are called
 148      */
 149     @Test(dataProvider = "rowSetType")
 150     public void baseRowSetTest0006(StubBaseRowSet rs) throws Exception {
 151         TestRowSetListener rsl = new TestRowSetListener();
 152         rs.addRowSetListener(rsl);
 153         rs.notifyRowSetChanged();
 154         rs.notifyRowChanged();
 155         rs.notifyCursorMoved();
 156         assertTrue(rsl.isNotified(
 157                 TestRowSetListener.CURSOR_MOVED | TestRowSetListener.ROWSET_CHANGED
 158                 | TestRowSetListener.ROW_CHANGED));
 159     }
 160 
 161 
 162     /*
 163      * Create multiple RowSetListeners and validate that notifyRowSetChanged,
 164      * notifyRowChanged() and notifyCursorMoved are called on all listeners
 165      */
 166     @Test(dataProvider = "rowSetType")
 167     public void baseRowSetTest0007(StubBaseRowSet rs) throws Exception {
 168         TestRowSetListener rsl = new TestRowSetListener();
 169         TestRowSetListener rsl2 = new TestRowSetListener();
 170         rs.addRowSetListener(rsl);
 171         rs.addRowSetListener(rsl2);
 172         rs.notifyRowSetChanged();
 173         rs.notifyRowChanged();
 174         rs.notifyCursorMoved();
 175         assertTrue(rsl.isNotified(
 176                 TestRowSetListener.CURSOR_MOVED | TestRowSetListener.ROWSET_CHANGED
 177                 | TestRowSetListener.ROW_CHANGED));
 178         assertTrue(rsl2.isNotified(
 179                 TestRowSetListener.CURSOR_MOVED | TestRowSetListener.ROWSET_CHANGED
 180                 | TestRowSetListener.ROW_CHANGED));
 181     }
 182 
 183     /*
 184      * Create a RowSetListener and validate that notifyRowSetChanged is called,
 185      * remove the listener, invoke notifyRowSetChanged again and verify the
 186      * listner is not called
 187      */
 188     @Test(dataProvider = "rowSetType")
 189     public void baseRowSetTest0008(StubBaseRowSet rs) throws Exception {
 190         TestRowSetListener rsl = new TestRowSetListener();
 191         rs.addRowSetListener(rsl);
 192         rs.notifyRowSetChanged();
 193         assertTrue(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
 194         // Clear the flag indicating the listener has been called
 195         rsl.resetFlag();
 196         rs.removeRowSetListener(rsl);
 197         rs.notifyRowSetChanged();
 198         assertFalse(rsl.isNotified(TestRowSetListener.ROWSET_CHANGED));
 199     }
 200 
 201     /*
 202      * Set the base parameters and validate that the value set is
 203      * the correct type and value
 204      */
 205     @Test(dataProvider = "testBaseParameters")
 206     public void baseRowSetTest0009(int pos, Object o) throws Exception {
 207         assertTrue(getParam(pos, o).getClass().isInstance(o));
 208         assertTrue(o.equals(getParam(pos, o)));
 209     }
 210 
 211     /*
 212      * Set the complex parameters and validate that the value set is
 213      * the correct type
 214      */
 215     @Test(dataProvider = "testAdvancedParameters")
 216     public void baseRowSetTest0010(int pos, Object o) throws Exception {
 217         assertTrue(getParam(pos, o).getClass().isInstance(o));
 218     }
 219 
 220     /*
 221      * Validate setNull specifying the supported type values
 222      */
 223     @Test(dataProvider = "jdbcTypes")
 224     public void baseRowSetTest0011(Integer type) throws Exception {
 225         brs = new StubBaseRowSet();
 226         brs.setNull(1, type);
 227         assertTrue(checkNullParam(1, type, null));
 228     }
 229 
 230     /*
 231      * Validate setNull specifying the supported type values and that
 232      * typeName is set internally
 233      */
 234     @Test(dataProvider = "jdbcTypes")
 235     public void baseRowSetTest0012(Integer type) throws Exception {
 236         brs = new StubBaseRowSet();
 237         brs.setNull(1, type, "SUPERHERO");
 238         assertTrue(checkNullParam(1, type, "SUPERHERO"));
 239     }
 240 
 241     /*
 242      *  Validate that setDate sets the specified Calendar internally
 243      */
 244     @Test()
 245     public void baseRowSetTest0013() throws Exception {
 246         Calendar cal = Calendar.getInstance();
 247         brs = new StubBaseRowSet();
 248         brs.setDate(1, Date.valueOf(LocalDate.now()), cal);
 249         assertTrue(checkCalendarParam(1, cal));
 250     }
 251 
 252     /*
 253      *  Validate that setTime sets the specified Calendar internally
 254      */
 255     @Test()
 256     public void baseRowSetTest0014() throws Exception {
 257         Calendar cal = Calendar.getInstance();
 258         brs = new StubBaseRowSet();
 259         brs.setTime(1, Time.valueOf(LocalTime.now()), cal);
 260         assertTrue(checkCalendarParam(1, cal));
 261     }
 262 
 263     /*
 264      *  Validate that setTimestamp sets the specified Calendar internally
 265      */
 266     @Test()
 267     public void baseRowSetTest0015() throws Exception {
 268         Calendar cal = Calendar.getInstance();
 269         brs = new StubBaseRowSet();
 270         brs.setTimestamp(1, Timestamp.valueOf(LocalDateTime.now()), cal);
 271         assertTrue(checkCalendarParam(1, cal));
 272     }
 273 
 274     /*
 275      * Validate that initParams() initializes the parameters
 276      */
 277     @Test(dataProvider = "rowSetType")
 278     public void baseRowSetTest0016(StubBaseRowSet rs) throws Exception {
 279         rs.setInt(1, 1);
 280         rs.initParams();
 281         assertTrue(rs.getParams().length == 0);
 282     }
 283 
 284 
 285     /*
 286      * DataProvider used to set parameters for basic types that are supported
 287      */
 288     @DataProvider(name = "testBaseParameters")
 289     private Object[][] testBaseParameters() throws SQLException {
 290         Integer aInt = 1;
 291         Long aLong = Long.MAX_VALUE;
 292         Short aShort = Short.MIN_VALUE;
 293         BigDecimal bd = BigDecimal.ONE;
 294         Double aDouble = Double.MAX_VALUE;
 295         Date aDate = Date.valueOf(LocalDate.now());
 296         Time aTime = Time.valueOf(LocalTime.now());
 297         Timestamp aTimeStamp = Timestamp.valueOf(LocalDateTime.now());
 298         Calendar cal = Calendar.getInstance();
 299         Boolean aBoolean = true;
 300         Float aFloat = 1.5f;
 301         Byte aByte = 1;
 302         brs = new StubBaseRowSet();
 303 
 304         brs.setInt(1, aInt);
 305         brs.setString(2, query);
 306         brs.setLong(3, aLong);
 307         brs.setBoolean(4, aBoolean);
 308         brs.setShort(5, aShort);
 309         brs.setDouble(6, aDouble);
 310         brs.setBigDecimal(7, bd);
 311         brs.setFloat(8, aFloat);
 312         brs.setByte(9, aByte);
 313         brs.setDate(10, aDate);
 314         brs.setTime(11, aTime);
 315         brs.setTimestamp(12, aTimeStamp);
 316         brs.setDate(13, aDate, cal);
 317         brs.setTime(14, aTime, cal);
 318         brs.setTimestamp(15, aTimeStamp);
 319         brs.setObject(16, query);
 320         brs.setObject(17, query, Types.CHAR);
 321         brs.setObject(18, query, Types.CHAR, 0);
 322 
 323         return new Object[][]{
 324             {1, aInt},
 325             {2, query},
 326             {3, aLong},
 327             {4, aBoolean},
 328             {5, aShort},
 329             {6, aDouble},
 330             {7, bd},
 331             {8, aFloat},
 332             {9, aByte},
 333             {10, aDate},
 334             {11, aTime},
 335             {12, aTimeStamp},
 336             {13, aDate},
 337             {14, aTime},
 338             {15, aTimeStamp},
 339             {16, query},
 340             {17, query},
 341             {18, query}
 342 
 343         };
 344     }
 345 
 346     /*
 347      * DataProvider used to set advanced parameters for types that are supported
 348      */
 349     @DataProvider(name = "testAdvancedParameters")
 350     private Object[][] testAdvancedParameters() throws SQLException {
 351 
 352         byte[] bytes = new byte[10];
 353         Ref aRef = new SerialRef(new StubRef("INTEGER", query));
 354         Array aArray = new SerialArray(new StubArray("INTEGER", new Object[1]));
 355         Blob aBlob = new SerialBlob(new StubBlob());
 356         Clob aClob = new SerialClob(new StubClob());
 357         Reader rdr = new StringReader(query);
 358         InputStream is = new StringBufferInputStream(query);;
 359         brs = new StubBaseRowSet();
 360         brs.setBytes(1, bytes);
 361         brs.setAsciiStream(2, is, query.length());
 362         brs.setRef(3, aRef);
 363         brs.setArray(4, aArray);
 364         brs.setBlob(5, aBlob);
 365         brs.setClob(6, aClob);
 366         brs.setBinaryStream(7, is, query.length());
 367         brs.setUnicodeStream(8, is, query.length());
 368         brs.setCharacterStream(9, rdr, query.length());
 369 
 370         return new Object[][]{
 371             {1, bytes},
 372             {2, is},
 373             {3, aRef},
 374             {4, aArray},
 375             {5, aBlob},
 376             {6, aClob},
 377             {7, is},
 378             {8, is},
 379             {9, rdr}
 380         };
 381     }
 382 
 383     /*
 384      *  Method that returns the specified parameter instance that was set via setXXX
 385      *  Note non-basic types are stored as an Object[] where the 1st element
 386      *  is the object instnace
 387      */
 388     @SuppressWarnings("unchecked")
 389     private <T> T getParam(int pos, T o) throws SQLException {
 390         Object[] params = brs.getParams();
 391         if (params[pos - 1] instanceof Object[]) {
 392             Object[] param = (Object[]) params[pos - 1];
 393             return (T) param[0];
 394         } else {
 395             return (T) params[pos - 1];
 396         }
 397     }
 398 
 399     /*
 400      * Utility method to validate parameters when the param is an Object[]
 401      */
 402     private boolean checkParam(int pos, int type, Object val) throws SQLException {
 403         boolean result = false;
 404         Object[] params = brs.getParams();
 405         if (params[pos - 1] instanceof Object[]) {
 406             Object[] param = (Object[]) params[pos - 1];
 407 
 408             if (param[0] == null) {
 409                 // setNull was used
 410                 if (param.length == 2 && (Integer) param[1] == type) {
 411                     result = true;
 412                 } else {
 413                     if (param.length == 3 && (Integer) param[1] == type
 414                             && val.equals(param[2])) {
 415                         result = true;
 416                     }
 417                 }
 418 
 419             } else if (param[0] instanceof java.util.Date) {
 420                 // setDate/Time/Timestamp with a Calendar object
 421                 if (param[1] instanceof Calendar && val.equals(param[1])) {
 422                     result = true;
 423                 }
 424             }
 425         }
 426         return result;
 427     }
 428 
 429     /*
 430      * Wrapper method for validating that a null was set and the appropriate
 431      * type and typeName if applicable
 432      */
 433     private boolean checkNullParam(int pos, int type, String typeName) throws SQLException {
 434         return checkParam(pos, type, typeName);
 435     }
 436 
 437     /*
 438      *  Wrapper method for validating that a Calander was set
 439      */
 440     private boolean checkCalendarParam(int pos, Calendar cal) throws SQLException {
 441         // 2nd param is ignored when instanceof java.util.Date
 442         return checkParam(pos, Types.DATE, cal);
 443     }
 444 }