1 /*
   2  * Copyright (c) 2016, 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 
  24 import java.beans.BeanInfo;
  25 import java.beans.BeanProperty;
  26 import java.beans.IntrospectionException;
  27 import java.beans.Introspector;
  28 import java.beans.PropertyChangeListener;
  29 import java.beans.PropertyDescriptor;
  30 
  31 import java.util.Arrays;
  32 
  33 
  34 /**
  35  * @test
  36  * @bug 8132703 8132163 8132732 8132973 8154756 8132888
  37  * @summary Some check for BeanProperty annotation
  38  * @author a.stepanov
  39  * @run main BeanPropertyTest
  40  */
  41 
  42 
  43 public class BeanPropertyTest {
  44 
  45     private final static String  DESCRIPTION = "TEST";
  46     private final static boolean BOUND       = true;
  47     private final static boolean EXPERT      = false;
  48     private final static boolean HIDDEN      = true;
  49     private final static boolean PREFERRED   = false;
  50     private final static boolean REQUIRED    = true;
  51     private final static boolean UPDATE      = false;
  52     private final static String
  53         V_NAME  = "javax.swing.SwingConstants.TOP",
  54         V_SHORT = "TOP",
  55         V = Integer.toString(javax.swing.SwingConstants.TOP);
  56     private final static int X = javax.swing.SwingConstants.TOP;
  57 
  58     private final static String DESCRIPTION_2 = "XYZ";
  59 
  60 
  61     // ---------- test cases ----------
  62 
  63     public static class G01 {
  64 
  65         private final static String TESTCASE = "arbitrary getter name";
  66 
  67         private final int x = X;
  68 
  69         @BeanProperty(
  70             description  = DESCRIPTION,
  71             bound        = BOUND,
  72             expert       = EXPERT,
  73             hidden       = HIDDEN,
  74             preferred    = PREFERRED,
  75             required     = REQUIRED,
  76             visualUpdate = UPDATE,
  77             enumerationValues = {V_NAME})
  78         public int get1() { return x; }
  79 
  80         public void addPropertyChangeListener(PropertyChangeListener l)    {}
  81         public void removePropertyChangeListener(PropertyChangeListener l) {}
  82     }
  83 
  84     public static class S01 {
  85 
  86         private final static String TESTCASE = "arbitrary setter name";
  87 
  88         private int x;
  89 
  90         @BeanProperty(
  91             description  = DESCRIPTION,
  92             bound        = BOUND,
  93             expert       = EXPERT,
  94             hidden       = HIDDEN,
  95             preferred    = PREFERRED,
  96             required     = REQUIRED,
  97             visualUpdate = UPDATE,
  98             enumerationValues = {V_NAME})
  99         public void setXXXXX(int v) { x = v; }
 100 
 101         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 102         public void removePropertyChangeListener(PropertyChangeListener l) {}
 103     }
 104 
 105     // JDK-8132703
 106     public static class G02 {
 107 
 108         private final static String TESTCASE = "arbitrary getter name";
 109 
 110         private final int x = X;
 111 
 112         @BeanProperty(
 113             description  = DESCRIPTION,
 114             bound        = BOUND,
 115             expert       = EXPERT,
 116             hidden       = HIDDEN,
 117             preferred    = PREFERRED,
 118             required     = REQUIRED,
 119             visualUpdate = UPDATE,
 120             enumerationValues = {V_NAME})
 121         public int get() { return x; }
 122 
 123         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 124         public void removePropertyChangeListener(PropertyChangeListener l) {}
 125     }
 126 
 127     // JDK-8132703
 128     public static class S02 {
 129 
 130         private final static String TESTCASE = "arbitrary setter name";
 131 
 132         private int x;
 133 
 134         @BeanProperty(
 135             description  = DESCRIPTION,
 136             bound        = BOUND,
 137             expert       = EXPERT,
 138             hidden       = HIDDEN,
 139             preferred    = PREFERRED,
 140             required     = REQUIRED,
 141             visualUpdate = UPDATE,
 142             enumerationValues = {V_NAME})
 143         public void set(int v) { x = v; }
 144 
 145         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 146         public void removePropertyChangeListener(PropertyChangeListener l) {}
 147     }
 148 
 149     // JDK-8132703
 150     public static class G03 {
 151 
 152         private final static String TESTCASE = "arbitrary getter name";
 153 
 154         private final int x = X;
 155 
 156         @BeanProperty(
 157             description  = DESCRIPTION,
 158             bound        = BOUND,
 159             expert       = EXPERT,
 160             hidden       = HIDDEN,
 161             preferred    = PREFERRED,
 162             required     = REQUIRED,
 163             visualUpdate = UPDATE,
 164             enumerationValues = {V_NAME})
 165         public int GetX() { return x; }
 166 
 167         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 168         public void removePropertyChangeListener(PropertyChangeListener l) {}
 169     }
 170 
 171     // JDK-8132703
 172     public static class S03 {
 173 
 174         private final static String TESTCASE = "arbitrary setter name";
 175 
 176         private int x;
 177 
 178         @BeanProperty(
 179             description  = DESCRIPTION,
 180             bound        = BOUND,
 181             expert       = EXPERT,
 182             hidden       = HIDDEN,
 183             preferred    = PREFERRED,
 184             required     = REQUIRED,
 185             visualUpdate = UPDATE,
 186             enumerationValues = {V_NAME})
 187         public void SetX(int v) { x = v; }
 188 
 189         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 190         public void removePropertyChangeListener(PropertyChangeListener l) {}
 191     }
 192 
 193     // JDK-8132163
 194     public static class G04 {
 195 
 196         private final static String TESTCASE = "arbitrary getter return type";
 197 
 198         private final int x = X;
 199 
 200         @BeanProperty(
 201             description  = DESCRIPTION,
 202             bound        = BOUND,
 203             expert       = EXPERT,
 204             hidden       = HIDDEN,
 205             preferred    = PREFERRED,
 206             required     = REQUIRED,
 207             visualUpdate = UPDATE,
 208             enumerationValues = {V_NAME})
 209         public Object getX() { return x; }
 210 
 211         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 212         public void removePropertyChangeListener(PropertyChangeListener l) {}
 213     }
 214 
 215     // JDK-8132163
 216     public static class S04 {
 217 
 218         private final static String TESTCASE = "arbitrary setter argument type";
 219 
 220         private int x;
 221 
 222         @BeanProperty(
 223             description  = DESCRIPTION,
 224             bound        = BOUND,
 225             expert       = EXPERT,
 226             hidden       = HIDDEN,
 227             preferred    = PREFERRED,
 228             required     = REQUIRED,
 229             visualUpdate = UPDATE,
 230             enumerationValues = {V_NAME})
 231         public void setX(short v) { x = v; }
 232 
 233         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 234         public void removePropertyChangeListener(PropertyChangeListener l) {}
 235     }
 236 
 237     public static class G05 {
 238 
 239         private final static String TESTCASE =
 240             "annotated getter + arbitrary setter argument type";
 241 
 242         private int x;
 243 
 244         @BeanProperty(
 245             description  = DESCRIPTION,
 246             bound        = BOUND,
 247             expert       = EXPERT,
 248             hidden       = HIDDEN,
 249             preferred    = PREFERRED,
 250             required     = REQUIRED,
 251             visualUpdate = UPDATE,
 252             enumerationValues = {V_NAME})
 253         public int getX() { return x; }
 254         public void setX(short v) { x = v; }
 255 
 256 
 257         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 258         public void removePropertyChangeListener(PropertyChangeListener l) {}
 259     }
 260 
 261     // JDK-8132163
 262     public static class S05 {
 263 
 264         private final static String TESTCASE =
 265             "annotated setter + arbitrary getter return type";
 266 
 267         private int x;
 268 
 269         @BeanProperty(
 270             description  = DESCRIPTION,
 271             bound        = BOUND,
 272             expert       = EXPERT,
 273             hidden       = HIDDEN,
 274             preferred    = PREFERRED,
 275             required     = REQUIRED,
 276             visualUpdate = UPDATE,
 277             enumerationValues = {V_NAME})
 278         public void setX(int v) { x = v; }
 279         public Object getX() { return x; }
 280 
 281         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 282         public void removePropertyChangeListener(PropertyChangeListener l) {}
 283     }
 284 
 285     public static class G06 {
 286 
 287         private final static String TESTCASE = "indexed getter";
 288 
 289         private final int x[] = {X, X, X};
 290 
 291         @BeanProperty(
 292             description  = DESCRIPTION,
 293             bound        = BOUND,
 294             expert       = EXPERT,
 295             hidden       = HIDDEN,
 296             preferred    = PREFERRED,
 297             required     = REQUIRED,
 298             visualUpdate = UPDATE,
 299             enumerationValues = {V_NAME})
 300         public int getX(int i) throws IndexOutOfBoundsException {
 301             if (i < 0 || i >= x.length) {
 302                 throw new IndexOutOfBoundsException(); }
 303             return x[i];
 304         }
 305 
 306         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 307         public void removePropertyChangeListener(PropertyChangeListener l) {}
 308     }
 309 
 310     public static class S06 {
 311 
 312         private final static String TESTCASE = "indexed setter";
 313 
 314         private final int x[] = {X, X, X};
 315 
 316         @BeanProperty(
 317             description  = DESCRIPTION,
 318             bound        = BOUND,
 319             expert       = EXPERT,
 320             hidden       = HIDDEN,
 321             preferred    = PREFERRED,
 322             required     = REQUIRED,
 323             visualUpdate = UPDATE,
 324             enumerationValues = {V_NAME})
 325         public void setX(int i, int v) throws IndexOutOfBoundsException {
 326             if (i < 0 || i >= x.length) {
 327                 throw new IndexOutOfBoundsException(); }
 328             x[i] = v;
 329         }
 330 
 331         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 332         public void removePropertyChangeListener(PropertyChangeListener l) {}
 333     }
 334 
 335     public static class G07 {
 336 
 337         private final static String TESTCASE =
 338             "indexed (annotated) + non-indexed getters";
 339 
 340         private final int x[] = {X, X, X};
 341 
 342         @BeanProperty(
 343             description  = DESCRIPTION,
 344             bound        = BOUND,
 345             expert       = EXPERT,
 346             hidden       = HIDDEN,
 347             preferred    = PREFERRED,
 348             required     = REQUIRED,
 349             visualUpdate = UPDATE,
 350             enumerationValues = {V_NAME})
 351         public int getX(int i) throws IndexOutOfBoundsException {
 352             if (i < 0 || i >= x.length) {
 353                 throw new IndexOutOfBoundsException(); }
 354             return x[i];
 355         }
 356 
 357         public int[] getX() { return x; }
 358 
 359         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 360         public void removePropertyChangeListener(PropertyChangeListener l) {}
 361     }
 362 
 363     public static class S07 {
 364 
 365         private final static String TESTCASE =
 366             "indexed (annotated) + non-indexed setters";
 367 
 368         private int x[] = new int[3];
 369 
 370         @BeanProperty(
 371             description  = DESCRIPTION,
 372             bound        = BOUND,
 373             expert       = EXPERT,
 374             hidden       = HIDDEN,
 375             preferred    = PREFERRED,
 376             required     = REQUIRED,
 377             visualUpdate = UPDATE,
 378             enumerationValues = {V_NAME})
 379         public void setX(int i, int v) throws IndexOutOfBoundsException {
 380             if (i < 0 || i >= x.length) {
 381                 throw new IndexOutOfBoundsException(); }
 382             x[i] = v;
 383         }
 384 
 385         public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
 386 
 387         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 388         public void removePropertyChangeListener(PropertyChangeListener l) {}
 389     }
 390 
 391     // JDK-8132732
 392     public static class G08 {
 393 
 394         private final static String TESTCASE =
 395             "non-indexed (annotated) + indexed getters";
 396 
 397         private final int x[] = {X, X, X};
 398 
 399         @BeanProperty(
 400             description  = DESCRIPTION,
 401             bound        = BOUND,
 402             expert       = EXPERT,
 403             hidden       = HIDDEN,
 404             preferred    = PREFERRED,
 405             required     = REQUIRED,
 406             visualUpdate = UPDATE,
 407             enumerationValues = {V_NAME})
 408         public int[] getX() { return x; }
 409 
 410         public int getX(int i) throws IndexOutOfBoundsException {
 411             if (i < 0 || i >= x.length) {
 412                 throw new IndexOutOfBoundsException(); }
 413             return x[i];
 414         }
 415 
 416         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 417         public void removePropertyChangeListener(PropertyChangeListener l) {}
 418     }
 419 
 420     // JDK-8132732
 421     public static class S08 {
 422 
 423         private final static String TESTCASE =
 424             "non-indexed (annotated) + indexed setters";
 425 
 426         private int x[] = new int[3];
 427 
 428         @BeanProperty(
 429             description  = DESCRIPTION,
 430             bound        = BOUND,
 431             expert       = EXPERT,
 432             hidden       = HIDDEN,
 433             preferred    = PREFERRED,
 434             required     = REQUIRED,
 435             visualUpdate = UPDATE,
 436             enumerationValues = {V_NAME})
 437         public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
 438 
 439         public void setX(int i, int v) throws IndexOutOfBoundsException {
 440             if (i < 0 || i >= x.length) {
 441                 throw new IndexOutOfBoundsException(); }
 442             x[i] = v;
 443         }
 444 
 445         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 446         public void removePropertyChangeListener(PropertyChangeListener l) {}
 447     }
 448 
 449     // JDK-8132732
 450     public static class G09 {
 451 
 452         private final static String TESTCASE = "two annotated getters";
 453 
 454         private final int x[] = {X, X, X};
 455 
 456         @BeanProperty(
 457             description  = DESCRIPTION,
 458             bound        = BOUND,
 459             expert       = EXPERT,
 460             hidden       = HIDDEN,
 461             preferred    = PREFERRED,
 462             required     = REQUIRED,
 463             visualUpdate = UPDATE,
 464             enumerationValues = {V_NAME})
 465         public int[] getX() { return x; }
 466 
 467         @BeanProperty(
 468             description  = DESCRIPTION_2,
 469             bound        = !BOUND,
 470             expert       = !EXPERT,
 471             hidden       = !HIDDEN,
 472             preferred    = !PREFERRED,
 473             required     = !REQUIRED,
 474             visualUpdate = !UPDATE)
 475         public int getX(int i) throws IndexOutOfBoundsException {
 476             if (i < 0 || i >= x.length) {
 477                 throw new IndexOutOfBoundsException(); }
 478             return x[i];
 479         }
 480 
 481         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 482         public void removePropertyChangeListener(PropertyChangeListener l) {}
 483     }
 484 
 485     // JDK-8132732
 486     public static class S09 {
 487 
 488         private final static String TESTCASE = "two annotated setters";
 489 
 490         private int x[] = new int[3];
 491 
 492         @BeanProperty(
 493             description  = DESCRIPTION,
 494             bound        = BOUND,
 495             expert       = EXPERT,
 496             hidden       = HIDDEN,
 497             preferred    = PREFERRED,
 498             required     = REQUIRED,
 499             visualUpdate = UPDATE,
 500             enumerationValues = {V_NAME})
 501         public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
 502 
 503         @BeanProperty(
 504             description  = DESCRIPTION_2,
 505             bound        = !BOUND,
 506             expert       = !EXPERT,
 507             hidden       = !HIDDEN,
 508             preferred    = !PREFERRED,
 509             required     = !REQUIRED,
 510             visualUpdate = !UPDATE)
 511         public void setX(int i, int v) throws IndexOutOfBoundsException {
 512             if (i < 0 || i >= x.length) {
 513                 throw new IndexOutOfBoundsException(); }
 514             x[i] = v;
 515         }
 516 
 517 
 518         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 519         public void removePropertyChangeListener(PropertyChangeListener l) {}
 520     }
 521 
 522     public static class G10 {
 523 
 524         private final static String TESTCASE =
 525             "getter + similarly named field";
 526 
 527         public int prop, Prop, setProp, getProp;
 528 
 529         @BeanProperty(
 530             description  = DESCRIPTION,
 531             bound        = BOUND,
 532             expert       = EXPERT,
 533             hidden       = HIDDEN,
 534             preferred    = PREFERRED,
 535             required     = REQUIRED,
 536             visualUpdate = UPDATE,
 537             enumerationValues = {V_NAME})
 538         public int getProp() { return X; }
 539         public void setProp(int v) { prop = Prop = setProp = getProp = v; }
 540 
 541         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 542         public void removePropertyChangeListener(PropertyChangeListener l) {}
 543     }
 544 
 545     public static class S10 {
 546 
 547         private final static String TESTCASE =
 548             "setter + similarly named field";
 549 
 550         public int prop, Prop, setProp, getProp;
 551 
 552         private int x;
 553 
 554         @BeanProperty(
 555             description  = DESCRIPTION,
 556             bound        = BOUND,
 557             expert       = EXPERT,
 558             hidden       = HIDDEN,
 559             preferred    = PREFERRED,
 560             required     = REQUIRED,
 561             visualUpdate = UPDATE,
 562             enumerationValues = {V_NAME})
 563         public int getProp() { return x; }
 564         public void setProp(int v) { x = v; }
 565 
 566         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 567         public void removePropertyChangeListener(PropertyChangeListener l) {}
 568     }
 569 
 570     public static class G11 {
 571 
 572         private final static String TESTCASE =
 573             "getter + similarly named field of other type";
 574 
 575         public Object prop, Prop, setProp, getProp;
 576 
 577         @BeanProperty(
 578             description  = DESCRIPTION,
 579             bound        = BOUND,
 580             expert       = EXPERT,
 581             hidden       = HIDDEN,
 582             preferred    = PREFERRED,
 583             required     = REQUIRED,
 584             visualUpdate = UPDATE,
 585             enumerationValues = {V_NAME})
 586         public int getProp() { return X; }
 587         public void setProp(int v) { prop = Prop = setProp = getProp = v; }
 588 
 589         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 590         public void removePropertyChangeListener(PropertyChangeListener l) {}
 591     }
 592 
 593     public static class S11 {
 594 
 595         private final static String TESTCASE =
 596             "setter + similarly named field of other type";
 597 
 598         public String prop, Prop, setProp, getProp;
 599 
 600         private int x;
 601 
 602         @BeanProperty(
 603             description  = DESCRIPTION,
 604             bound        = BOUND,
 605             expert       = EXPERT,
 606             hidden       = HIDDEN,
 607             preferred    = PREFERRED,
 608             required     = REQUIRED,
 609             visualUpdate = UPDATE,
 610             enumerationValues = {V_NAME})
 611         public int getProp() { return x; }
 612         public void setProp(int v) { x = v; }
 613 
 614         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 615         public void removePropertyChangeListener(PropertyChangeListener l) {}
 616     }
 617 
 618     // JDK-8132163
 619     public static class G12 {
 620 
 621         private final static String TESTCASE =
 622             "getter having wrapper class return type";
 623 
 624         private final int x = X;
 625 
 626         @BeanProperty(
 627             description  = DESCRIPTION,
 628             bound        = BOUND,
 629             expert       = EXPERT,
 630             hidden       = HIDDEN,
 631             preferred    = PREFERRED,
 632             required     = REQUIRED,
 633             visualUpdate = UPDATE,
 634             enumerationValues = {V_NAME})
 635         public Integer getProp() { return x; }
 636 
 637         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 638         public void removePropertyChangeListener(PropertyChangeListener l) {}
 639     }
 640 
 641     // JDK-8132163
 642     public static class S12 {
 643 
 644         private final static String TESTCASE =
 645             "setter with wrapper class argument type";
 646 
 647         private int x;
 648 
 649         @BeanProperty(
 650             description  = DESCRIPTION,
 651             bound        = BOUND,
 652             expert       = EXPERT,
 653             hidden       = HIDDEN,
 654             preferred    = PREFERRED,
 655             required     = REQUIRED,
 656             visualUpdate = UPDATE,
 657             enumerationValues = {V_NAME})
 658         public void setX(Integer v) { x = v; }
 659 
 660         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 661         public void removePropertyChangeListener(PropertyChangeListener l) {}
 662     }
 663 
 664     public static class G13 {
 665 
 666         private final static String TESTCASE =
 667             "getter + overloading methods";
 668 
 669         private final int x = X;
 670 
 671         @BeanProperty(
 672             description  = DESCRIPTION,
 673             bound        = BOUND,
 674             expert       = EXPERT,
 675             hidden       = HIDDEN,
 676             preferred    = PREFERRED,
 677             required     = REQUIRED,
 678             visualUpdate = UPDATE,
 679             enumerationValues = {V_NAME})
 680         public int getX() { return x; }
 681         public int getX(boolean arg) { return (arg ? x : 0); }
 682         public int getX(int ... dummy) { return 0; }
 683 
 684         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 685         public void removePropertyChangeListener(PropertyChangeListener l) {}
 686     }
 687 
 688     // JDK-8154756
 689     public static class S13 {
 690 
 691         private final static String TESTCASE =
 692             "setter + overloading methods";
 693 
 694         private int x;
 695 
 696         @BeanProperty(
 697             description  = DESCRIPTION,
 698             bound        = BOUND,
 699             expert       = EXPERT,
 700             hidden       = HIDDEN,
 701             preferred    = PREFERRED,
 702             required     = REQUIRED,
 703             visualUpdate = UPDATE,
 704             enumerationValues = {V_NAME})
 705         public void setX(int v) { x = v; }
 706         public int  setX() { return (x = X); }
 707         public void setX(int ... dummy) {}
 708         private void setX(Object ... dummy) {}
 709 
 710 
 711         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 712         public void removePropertyChangeListener(PropertyChangeListener l) {}
 713     }
 714 
 715 
 716     // JDK-8132888
 717     public static class G14 {
 718 
 719         private final static String TESTCASE = "non-public getter";
 720 
 721         private final int x = X;
 722 
 723         @BeanProperty(
 724             description  = DESCRIPTION,
 725             bound        = BOUND,
 726             expert       = EXPERT,
 727             hidden       = HIDDEN,
 728             preferred    = PREFERRED,
 729             required     = REQUIRED,
 730             visualUpdate = UPDATE,
 731             enumerationValues = {V_NAME})
 732         int getX() { return x; } // getter is not public
 733 
 734         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 735         public void removePropertyChangeListener(PropertyChangeListener l) {}
 736     }
 737 
 738     // JDK-8132888
 739     public static class S14 {
 740 
 741         private final static String TESTCASE = "non-public setter";
 742 
 743         private int x;
 744 
 745         @BeanProperty(
 746             description  = DESCRIPTION,
 747             bound        = BOUND,
 748             expert       = EXPERT,
 749             hidden       = HIDDEN,
 750             preferred    = PREFERRED,
 751             required     = REQUIRED,
 752             visualUpdate = UPDATE,
 753             enumerationValues = {V_NAME})
 754         void setX(int v) { x = v; } // setter is not public
 755 
 756         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 757         public void removePropertyChangeListener(PropertyChangeListener l) {}
 758     }
 759 
 760     public static class getX {
 761 
 762         private final static String TESTCASE =
 763             "class name coincides with getter name";
 764 
 765         private int x;
 766 
 767         @BeanProperty(
 768             description  = DESCRIPTION,
 769             bound        = BOUND,
 770             expert       = EXPERT,
 771             hidden       = HIDDEN,
 772             preferred    = PREFERRED,
 773             required     = REQUIRED,
 774             visualUpdate = UPDATE,
 775             enumerationValues = {V_NAME})
 776         public int  getX() { return x; }
 777         public void setX(int v) { x = v; }
 778 
 779         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 780         public void removePropertyChangeListener(PropertyChangeListener l) {}
 781     }
 782 
 783     public static class setX {
 784 
 785         private final static String TESTCASE =
 786             "class name coincides with setter name";
 787 
 788         private int x;
 789 
 790         @BeanProperty(
 791             description  = DESCRIPTION,
 792             bound        = BOUND,
 793             expert       = EXPERT,
 794             hidden       = HIDDEN,
 795             preferred    = PREFERRED,
 796             required     = REQUIRED,
 797             visualUpdate = UPDATE,
 798             enumerationValues = {V_NAME})
 799         public void setX(int v) { x = v; }
 800         public int  getX() { return x; }
 801 
 802         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 803         public void removePropertyChangeListener(PropertyChangeListener l) {}
 804     }
 805 
 806     // JDK-8132973
 807     public static class GS {
 808 
 809         private final static String TESTCASE =
 810             "both getter and setter are annotated";
 811 
 812         private int x;
 813 
 814         @BeanProperty(
 815             description  = DESCRIPTION,
 816             bound        = BOUND,
 817             expert       = EXPERT,
 818             hidden       = HIDDEN,
 819             preferred    = PREFERRED,
 820             required     = REQUIRED,
 821             visualUpdate = UPDATE,
 822             enumerationValues = {V_NAME})
 823         public int getX() { return x; }
 824 
 825         @BeanProperty(
 826             description  = DESCRIPTION_2,
 827             bound        = !BOUND,
 828             expert       = !EXPERT,
 829             hidden       = !HIDDEN,
 830             preferred    = !PREFERRED,
 831             required     = !REQUIRED,
 832             visualUpdate = !UPDATE)
 833         public void setX(int v) { x = v; }
 834 
 835 
 836         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 837         public void removePropertyChangeListener(PropertyChangeListener l) {}
 838     }
 839 
 840 
 841 
 842 
 843     // ---------- checks ----------
 844 
 845     private static boolean check(String what, boolean v, boolean ref) {
 846 
 847         boolean ok = (v == ref);
 848         if (!ok) { System.out.println(
 849             "invalid " + what + ": " + v + ", expected: " + ref); }
 850         return ok;
 851     }
 852 
 853     private static boolean checkInfo(BeanInfo i) {
 854 
 855         System.out.println("checking info...");
 856 
 857         PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
 858         int nd = descriptors.length;
 859         if (nd != 1) {
 860             System.out.println("invalid number of descriptors: " + nd);
 861             return false;
 862         }
 863 
 864         PropertyDescriptor d = descriptors[0];
 865 
 866         String descr = d.getShortDescription();
 867         boolean ok = descr.equals(DESCRIPTION);
 868         if (!ok) { System.out.println("invalid description: " + descr +
 869                 ", expected: " + DESCRIPTION); }
 870 
 871         ok &= check("isBound",  d.isBound(),  BOUND);
 872         ok &= check("isExpert", d.isExpert(), EXPERT);
 873         ok &= check("isHidden", d.isHidden(), HIDDEN);
 874         ok &= check("isPreferred", d.isPreferred(), PREFERRED);
 875         ok &= check("required", (boolean) d.getValue("required"), REQUIRED);
 876         ok &= check("visualUpdate",
 877             (boolean) d.getValue("visualUpdate"), UPDATE);
 878 
 879         Object vals[] = (Object[]) d.getValue("enumerationValues");
 880         if (vals == null) {
 881             System.out.println("null enumerationValues");
 882             return false;
 883         }
 884 
 885         boolean okVals = (
 886             (vals.length == 3) &&
 887              vals[0].toString().equals(V_SHORT) &&
 888              vals[1].toString().equals(V)       &&
 889              vals[2].toString().equals(V_NAME));
 890 
 891         if (!okVals) { System.out.println("invalid enumerationValues"); }
 892 
 893         return (ok && okVals);
 894     }
 895 
 896     private static boolean checkAlternativeInfo(BeanInfo i) {
 897 
 898         System.out.println("checking alternative info...");
 899 
 900         PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
 901         int nd = descriptors.length;
 902         if (nd != 1) {
 903             System.out.println("invalid number of descriptors: " + nd);
 904             return false;
 905         }
 906 
 907         PropertyDescriptor d = descriptors[0];
 908 
 909         String descr = d.getShortDescription();
 910         boolean ok = descr.equals(DESCRIPTION_2);
 911         if (!ok) { System.out.println("invalid alternative description: " +
 912             descr + ", expected: " + DESCRIPTION_2); }
 913 
 914         ok &= check("isBound",  d.isBound(),  !BOUND);
 915         ok &= check("isExpert", d.isExpert(), !EXPERT);
 916         ok &= check("isHidden", d.isHidden(), !HIDDEN);
 917         ok &= check("isPreferred", d.isPreferred(), !PREFERRED);
 918         ok &= check("required", (boolean) d.getValue("required"), !REQUIRED);
 919         ok &= check("visualUpdate",
 920             (boolean) d.getValue("visualUpdate"), !UPDATE);
 921 
 922         Object vals[] = (Object[]) d.getValue("enumerationValues");
 923         if (vals != null || vals.length > 0) {
 924             System.out.println("non-null enumerationValues");
 925             return false;
 926         }
 927 
 928         return ok;
 929     }
 930 
 931 
 932     private static boolean checkAlternative(Class<?> c) {
 933         return (
 934             c.equals(G09.class) ||
 935             c.equals(S09.class) ||
 936             c.equals(GS.class));
 937     }
 938 
 939 
 940     // ---------- run test ----------
 941 
 942     public static void main(String[] args) throws Exception {
 943 
 944         Class<?> cases[] = {
 945 
 946             G01.class, S01.class,
 947             // G02.class, S02.class, // TODO: please update after 8132703 fix
 948             // G03.class, S03.class, // TODO: please update after 8132703 fix
 949             // G04.class, S04.class, // TODO: please update after 8132163 fix
 950             G05.class, // S05.class, // TODO: please update after 8132163 fix
 951             G06.class, S06.class,
 952             G07.class, S07.class,
 953             // G08.class, S08.class, // TODO: please update after 8132732 fix
 954             // G09.class, S09.class, // TODO: please update after 8132732 fix
 955             G10.class, S10.class,
 956             G11.class, S11.class,
 957             // G12.class, S12.class, // TODO: please update after 8132163 fix
 958             G13.class, // S13.class, // TODO: please update after 8154756 fix
 959             // G14.class, S14.class, // TODO: please update after 8132888 fix or
 960                                      // remove these cases if it is not an issue
 961             // GS.class, // TODO: please update after 8132973 fix
 962             getX.class, setX.class
 963         };
 964 
 965         boolean passed = true;
 966 
 967         for (Class<?> c: cases) {
 968 
 969             java.lang.reflect.Field f = c.getDeclaredField("TESTCASE");
 970             f.setAccessible(true);
 971             String descr = f.get(c).toString();
 972 
 973             System.out.println("\n" + c.getSimpleName() + " (" + descr + "):");
 974             BeanInfo i;
 975             try { i = Introspector.getBeanInfo(c, Object.class); }
 976             catch (IntrospectionException e) { throw new RuntimeException(e); }
 977             boolean ok = checkInfo(i);
 978             if (checkAlternative(c)) {
 979                 ok |= checkAlternativeInfo(i);
 980             }
 981             System.out.println(ok ? "OK" : "NOK");
 982             passed = passed && ok;
 983         }
 984 
 985         if (!passed) { throw new RuntimeException("test failed"); }
 986         System.out.println("\ntest passed");
 987     }
 988 }