Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.print.cts;
     18 
     19 import static org.junit.Assert.assertEquals;
     20 
     21 import android.os.ParcelFileDescriptor;
     22 import android.print.PageRange;
     23 import android.print.PrintAttributes;
     24 import android.print.PrintAttributes.Margins;
     25 import android.print.PrintAttributes.MediaSize;
     26 import android.print.PrintAttributes.Resolution;
     27 import android.print.PrintDocumentAdapter;
     28 import android.print.PrintDocumentAdapter.LayoutResultCallback;
     29 import android.print.PrintDocumentAdapter.WriteResultCallback;
     30 import android.print.PrintDocumentInfo;
     31 import android.print.PrinterCapabilitiesInfo;
     32 import android.print.PrinterId;
     33 import android.print.PrinterInfo;
     34 import android.print.test.BasePrintTest;
     35 import android.print.test.services.FirstPrintService;
     36 import android.print.test.services.PrintServiceCallbacks;
     37 import android.print.test.services.PrinterDiscoverySessionCallbacks;
     38 import android.print.test.services.SecondPrintService;
     39 import android.print.test.services.StubbablePrinterDiscoverySession;
     40 import android.printservice.PrintJob;
     41 import android.support.test.runner.AndroidJUnit4;
     42 import android.util.Log;
     43 
     44 import org.junit.Before;
     45 import org.junit.Test;
     46 import org.junit.runner.RunWith;
     47 
     48 import java.util.ArrayList;
     49 import java.util.Arrays;
     50 import java.util.List;
     51 
     52 /**
     53  * Test that the print attributes are correctly propagated through the print framework
     54  */
     55 @RunWith(AndroidJUnit4.class)
     56 public class PrintAttributesTest extends BasePrintTest {
     57     private static final String LOG_TAG = "PrintAttributesTest";
     58     private final String PRINTER_NAME = "Test printer";
     59 
     60     private final Margins[] MIN_MARGINS = {
     61             new Margins(0, 0, 0, 0), new Margins(10, 10, 10, 10), new Margins(20, 20, 20, 20),
     62     };
     63 
     64     private final MediaSize MEDIA_SIZES[] = {
     65             MediaSize.ISO_A3, MediaSize.ISO_A4, MediaSize.ISO_A5
     66     };
     67 
     68     private final int COLOR_MODES[] = {
     69             PrintAttributes.COLOR_MODE_MONOCHROME, PrintAttributes.COLOR_MODE_COLOR
     70     };
     71 
     72     private final int DUPLEX_MODES[] = {
     73             PrintAttributes.DUPLEX_MODE_NONE, PrintAttributes.DUPLEX_MODE_LONG_EDGE,
     74             PrintAttributes.DUPLEX_MODE_SHORT_EDGE
     75     };
     76 
     77     private final Resolution RESOLUTIONS[] = {
     78             new Resolution("300x300", "300x300", 300, 300),
     79             new Resolution("600x600", "600x600", 600, 600),
     80             new Resolution("1200x1200", "1200x1200", 1200, 1200)
     81     };
     82 
     83     /**
     84      * Stores the {@link PrintAttributes} passed to the layout method
     85      */
     86     private PrintAttributes mLayoutAttributes;
     87     private static boolean sHasBeenSetup;
     88 
     89     /**
     90      * Create a new {@link PrintAttributes} object with the given properties.
     91      *
     92      * All properties can be null/0 to remain unset.
     93      *
     94      * @param mediaSize {@link MediaSize} to use
     95      * @param colorMode Color mode to use
     96      * @param duplexMode Duplex mode to use
     97      * @param resolution {@link Resolution} to use
     98      *
     99      * @return The newly created object or null if no properties are set
    100      */
    101     private PrintAttributes createAttributes(MediaSize mediaSize, int colorMode, int duplexMode,
    102             Resolution resolution) {
    103         if (mediaSize == null && colorMode == 0 && duplexMode == 0 && resolution == null) {
    104             return null;
    105         }
    106 
    107         PrintAttributes.Builder builder = new PrintAttributes.Builder();
    108 
    109         if (mediaSize != null) {
    110             builder.setMediaSize(mediaSize);
    111         }
    112 
    113         if (colorMode != 0) {
    114             builder.setColorMode(colorMode);
    115         }
    116 
    117         if (duplexMode != 0) {
    118             builder.setDuplexMode(duplexMode);
    119         }
    120 
    121         if (resolution != null) {
    122             builder.setResolution(resolution);
    123         }
    124 
    125         return builder.build();
    126     }
    127 
    128     /**
    129      * Create {@link PrinterDiscoverySessionCallbacks} with a single printer that has the given
    130      * capabilities
    131      *
    132      * @param minMargins The minMargins of the printer
    133      * @param mediaSizes The {@link MediaSize media sizes} supported by the printer
    134      * @param defaultMediaSize The default {@link MediaSize}
    135      * @param colorModes The color modes supported by the printer
    136      * @param defaultColorMode The default color mode
    137      * @param duplexModes The duplex modes supported by the printer
    138      * @param defaultDuplexMode The default duplex mode
    139      * @param resolutions The {@link Resolution resolutions} supported by the printer
    140      * @param defaultResolution The default {@link Resolution} to use
    141      *
    142      * @return New {@link PrinterDiscoverySessionCallbacks} with a single printer that has the
    143      *         given capabilities
    144      */
    145     private PrinterDiscoverySessionCallbacks createMockPrinterDiscoverySessionCallbacks(
    146             final Margins minMargins, final MediaSize mediaSizes[],
    147             final MediaSize defaultMediaSize, final int colorModes[], final int defaultColorMode,
    148             final int duplexModes[], final int defaultDuplexMode, final Resolution resolutions[],
    149             final Resolution defaultResolution) {
    150         return createMockPrinterDiscoverySessionCallbacks(invocation -> {
    151             StubbablePrinterDiscoverySession session =
    152                     ((PrinterDiscoverySessionCallbacks) invocation.getMock()).getSession();
    153 
    154             if (session.getPrinters().isEmpty()) {
    155                 List<PrinterInfo> printers = new ArrayList<>();
    156                 PrinterId printerId = session.getService().generatePrinterId(PRINTER_NAME);
    157 
    158                 PrinterCapabilitiesInfo.Builder builder =
    159                         new PrinterCapabilitiesInfo.Builder(printerId);
    160 
    161                 builder.setMinMargins(minMargins);
    162 
    163                 int mediaSizesLength = mediaSizes.length;
    164                 for (int i = 0; i < mediaSizesLength; i++) {
    165                     if (mediaSizes[i].equals(defaultMediaSize)) {
    166                         builder.addMediaSize(mediaSizes[i], true);
    167                     } else {
    168                         builder.addMediaSize(mediaSizes[i], false);
    169                     }
    170                 }
    171 
    172                 int colorModesMask = 0;
    173                 int colorModesLength = colorModes.length;
    174                 for (int i = 0; i < colorModesLength; i++) {
    175                     colorModesMask |= colorModes[i];
    176                 }
    177                 builder.setColorModes(colorModesMask, defaultColorMode);
    178 
    179                 int duplexModesMask = 0;
    180                 int duplexModeLength = duplexModes.length;
    181                 for (int i = 0; i < duplexModeLength; i++) {
    182                     duplexModesMask |= duplexModes[i];
    183                 }
    184                 builder.setDuplexModes(duplexModesMask, defaultDuplexMode);
    185 
    186                 int resolutionsLength = resolutions.length;
    187                 for (int i = 0; i < resolutionsLength; i++) {
    188                     if (resolutions[i].equals(defaultResolution)) {
    189                         builder.addResolution(resolutions[i], true);
    190                     } else {
    191                         builder.addResolution(resolutions[i], false);
    192                     }
    193                 }
    194 
    195                 PrinterInfo printer = new PrinterInfo.Builder(printerId, PRINTER_NAME,
    196                         PrinterInfo.STATUS_IDLE).setCapabilities(builder.build()).build();
    197                 printers.add(printer);
    198 
    199                 session.addPrinters(printers);
    200             }
    201             return null;
    202         }, null, null, invocation -> null, null, null, invocation -> {
    203             // Take a note onDestroy was called.
    204             onPrinterDiscoverySessionDestroyCalled();
    205             return null;
    206         });
    207     }
    208 
    209     /**
    210      * Create dummy {@link PrintServiceCallbacks}
    211      *
    212      * This is needed to as the print framework is trying to talk to any printer even if is not set
    213      * up.
    214      *
    215      * @return Dummy {@link PrintServiceCallbacks}
    216      */
    217     private PrintServiceCallbacks createDummyMockPrintServiceCallbacks() {
    218         return createMockPrintServiceCallbacks(null, null, null);
    219     }
    220 
    221     /**
    222      * Create a {@link PrintDocumentAdapter} that serves empty pages
    223      *
    224      * @return A new {@link PrintDocumentAdapter}
    225      */
    226     private PrintDocumentAdapter createMockPrintDocumentAdapter() {
    227         return createMockPrintDocumentAdapter(
    228                 invocation -> {
    229                     mLayoutAttributes = (PrintAttributes) invocation.getArguments()[1];
    230                     LayoutResultCallback callback =
    231                             (LayoutResultCallback) invocation.getArguments()[3];
    232                     PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
    233                             .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
    234                             .setPageCount(1)
    235                             .build();
    236                     callback.onLayoutFinished(info, false);
    237                     // Mark layout was called.
    238                     onLayoutCalled();
    239                     return null;
    240                 }, invocation -> {
    241                     Object[] args = invocation.getArguments();
    242                     PageRange[] pages = (PageRange[]) args[0];
    243                     ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
    244                     WriteResultCallback callback = (WriteResultCallback) args[3];
    245                     writeBlankPages(mLayoutAttributes, fd, pages[0].getStart(),
    246                             pages[0].getEnd());
    247                     fd.close();
    248                     callback.onWriteFinished(pages);
    249                     // Mark write was called.
    250                     onWriteCalled();
    251                     return null;
    252                 }, invocation -> {
    253                     // Mark finish was called.
    254                     onFinishCalled();
    255                     return null;
    256                 });
    257     }
    258 
    259     /**
    260      * Set up a single printer with the given capabilities
    261      *
    262      * @param minMargins The minMargins of the printer
    263      * @param mediaSizes The {@link MediaSize media sizes} supported by the printer
    264      * @param defaultMediaSize The default {@link MediaSize}
    265      * @param colorModes The color modes supported by the printer
    266      * @param defaultColorMode The default color mode
    267      * @param duplexModes The duplex modes supported by the printer
    268      * @param defaultDuplexMode The default duplex mode
    269      * @param resolutions The {@link Resolution resolutions} supported by the printer
    270      * @param defaultResolution The default {@link Resolution} to use
    271      *
    272      * @return A {@link PrintDocumentAdapter} that can be used for the new printer
    273      */
    274     private PrintDocumentAdapter setUpPrinter(Margins minMargins, MediaSize mediaSizes[],
    275             MediaSize defaultMediaSize, int colorModes[], int defaultColorMode, int duplexModes[],
    276             int defaultDuplexMode, Resolution resolutions[], Resolution defaultResolution) {
    277         final PrinterDiscoverySessionCallbacks sessionCallbacks =
    278                 createMockPrinterDiscoverySessionCallbacks(minMargins, mediaSizes,
    279                         defaultMediaSize, colorModes, defaultColorMode, duplexModes,
    280                         defaultDuplexMode, resolutions, defaultResolution);
    281 
    282         PrintServiceCallbacks serviceCallbacks = createMockPrintServiceCallbacks(
    283                 invocation -> sessionCallbacks,
    284                 invocation -> {
    285                     PrintJob printJob = (PrintJob) invocation.getArguments()[0];
    286                     // We pretend the job is handled immediately.
    287                     printJob.complete();
    288                     return null;
    289                 }, null);
    290 
    291         // Configure the print services.
    292         FirstPrintService.setCallbacks(serviceCallbacks);
    293 
    294         // We need to set up the second print service too, otherwise we get a null pointer in the
    295         // print framework
    296         SecondPrintService.setCallbacks(createDummyMockPrintServiceCallbacks());
    297 
    298         // Create a print adapter that respects the print contract.
    299         return createMockPrintDocumentAdapter();
    300     }
    301 
    302     /**
    303      * Check if a value is in an array.
    304      *
    305      * To be use instead of Arrays.asList(array).contains(value) for ints.
    306      *
    307      * @param array The array the value might be in
    308      * @param value The value to search for
    309      *
    310      * @return true iff the value is in the array
    311      */
    312     private boolean isInArray(final int array[], int value) {
    313         int arrayLength = array.length;
    314         for (int i = 0; i < arrayLength; i++) {
    315             if (array[i] == value) {
    316                 return true;
    317             }
    318         }
    319 
    320         return false;
    321     }
    322 
    323     @Before
    324     public void setUpServicesAndAdapter() throws Exception {
    325         if (!sHasBeenSetup) {
    326             // Set up printer with supported and default attributes
    327             PrintDocumentAdapter adapter =
    328                     setUpPrinter(MIN_MARGINS[0], MEDIA_SIZES, MEDIA_SIZES[0], COLOR_MODES,
    329                             COLOR_MODES[0], DUPLEX_MODES, DUPLEX_MODES[0], RESOLUTIONS,
    330                             RESOLUTIONS[0]);
    331 
    332             Log.d(LOG_TAG, "makeDefaultPrinter");
    333             // Make printer default. This is necessary as a different default printer might pre-select
    334             // its default attributes and thereby overrides the defaults of the tested printer.
    335             makeDefaultPrinter(adapter, PRINTER_NAME);
    336 
    337             sHasBeenSetup = true;
    338         }
    339 
    340         resetCounters();
    341     }
    342 
    343     /**
    344      * Flexible base test for all print attribute tests.
    345      *
    346      * Asserts that the default and suggested attributes are properly honored by the print
    347      * framework.
    348      *
    349      * @param minMargins The minMargins of the printer
    350      * @param mediaSizes The {@link MediaSize media sizes} supported by the printer
    351      * @param defaultMediaSize The default {@link MediaSize}
    352      * @param colorModes The color modes supported by the printer
    353      * @param defaultColorMode The default color mode
    354      * @param duplexModes The duplex modes supported by the printer
    355      * @param defaultDuplexMode The default duplex mode
    356      * @param resolutions The {@link Resolution resolutions} supported by the printer
    357      * @param defaultResolution The default {@link Resolution} to use
    358      * @param suggestedMediaSize The suggested {@link MediaSize} for the print job
    359      * @param suggestedColorMode The suggested color mode for the print job
    360      * @param suggestedDuplexMode The suggested duplex mode for the print job
    361      * @param suggestedResolution The suggested resolution for the print job
    362      *
    363      * @throws Exception If anything is unexpected
    364      */
    365     private void baseTest(Margins minMargins, MediaSize mediaSizes[],
    366             MediaSize defaultMediaSize, MediaSize suggestedMediaSize, int colorModes[],
    367             int defaultColorMode, int suggestedColorMode, int duplexModes[],
    368             int defaultDuplexMode, int suggestedDuplexMode, Resolution resolutions[],
    369             Resolution defaultResolution, Resolution suggestedResolution) throws Exception {
    370         PrintDocumentAdapter adapter =
    371                 setUpPrinter(minMargins, mediaSizes, defaultMediaSize, colorModes, defaultColorMode,
    372                         duplexModes, defaultDuplexMode, resolutions, defaultResolution);
    373 
    374         // Select suggested attributes
    375         PrintAttributes suggestedAttributes = createAttributes(suggestedMediaSize,
    376                 suggestedColorMode, suggestedDuplexMode, suggestedResolution);
    377 
    378         // Start print action and wait for layout, the result is stored in #layoutAttributes,
    379         // @see createMockPrintDocumentAdapter
    380         Log.d(LOG_TAG, "print");
    381         print(adapter, suggestedAttributes);
    382         Log.d(LOG_TAG, "waitForWriteAdapterCallback");
    383         waitForWriteAdapterCallback(1);
    384         Log.d(LOG_TAG, "clickPrintButton");
    385         clickPrintButton();
    386         Log.d(LOG_TAG, "waitForPrinterDiscoverySessionDestroyCallbackCalled");
    387         waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
    388 
    389         // It does not make sense to suggest minMargins, hence the print framework always picks
    390         // the one set up for the printer.
    391         assertEquals("Min margins not as expected", minMargins, mLayoutAttributes.getMinMargins());
    392 
    393         // Verify that the attributes are honored properly
    394         if (suggestedMediaSize != null && Arrays.asList(mediaSizes).contains(suggestedMediaSize)) {
    395             assertEquals("Media size not as suggested", suggestedMediaSize,
    396                     mLayoutAttributes.getMediaSize());
    397         } else {
    398             assertEquals("Media size not default", defaultMediaSize,
    399                     mLayoutAttributes.getMediaSize());
    400         }
    401 
    402         if (suggestedColorMode != 0 && isInArray(colorModes, suggestedColorMode)) {
    403             assertEquals("Color mode not as suggested", suggestedColorMode,
    404                     mLayoutAttributes.getColorMode());
    405         } else {
    406             assertEquals("Color mode not default", defaultColorMode,
    407                     mLayoutAttributes.getColorMode());
    408         }
    409 
    410         if (suggestedDuplexMode != 0 && isInArray(duplexModes, suggestedDuplexMode)) {
    411             assertEquals("Duplex mode not as suggested", suggestedDuplexMode,
    412                     mLayoutAttributes.getDuplexMode());
    413         } else {
    414             assertEquals("Duplex mode not default", defaultDuplexMode,
    415                     mLayoutAttributes.getDuplexMode());
    416         }
    417 
    418         if (suggestedResolution != null
    419                 && Arrays.asList(resolutions).contains(suggestedResolution)) {
    420             assertEquals("Resolution not as suggested", suggestedResolution,
    421                     mLayoutAttributes.getResolution());
    422         } else {
    423             assertEquals("Resolution not default", defaultResolution,
    424                     mLayoutAttributes.getResolution());
    425         }
    426     }
    427 
    428     /**
    429      * Test that attributes are as expected if the default attributes match the suggested ones.
    430      *
    431      * This test sets the default and suggested attributes to the first selection.
    432      *
    433      * @throws Exception If anything is unexpected
    434      */
    435     @Test
    436     public void defaultMatchesSuggested0() throws Exception {
    437         //       available     default          suggestion
    438         baseTest(              MIN_MARGINS[0],
    439                  MEDIA_SIZES,  MEDIA_SIZES[0],  MEDIA_SIZES[0],
    440                  COLOR_MODES,  COLOR_MODES[0],  COLOR_MODES[0],
    441                  DUPLEX_MODES, DUPLEX_MODES[0], DUPLEX_MODES[0],
    442                  RESOLUTIONS,  RESOLUTIONS[0],  RESOLUTIONS[0]);
    443     }
    444 
    445     /**
    446      * Test that attributes are as expected if the default attributes match the suggested ones.
    447      *
    448      * This test sets the default and suggested attributes to the second selection.
    449      *
    450      * @throws Exception If anything is unexpected
    451      */
    452     @Test
    453     public void defaultMatchesSuggested1() throws Exception {
    454         //       available     default          suggestion
    455         baseTest(              MIN_MARGINS[1],
    456                  MEDIA_SIZES,  MEDIA_SIZES[1],  MEDIA_SIZES[1],
    457                  COLOR_MODES,  COLOR_MODES[1],  COLOR_MODES[1],
    458                  DUPLEX_MODES, DUPLEX_MODES[1], DUPLEX_MODES[1],
    459                  RESOLUTIONS,  RESOLUTIONS[1],  RESOLUTIONS[1]);
    460     }
    461 
    462     /**
    463      * Test that attributes are as expected if the default attributes match the suggested ones.
    464      *
    465      * This test sets the default and suggested attributes to the third selection.
    466      *
    467      * @throws Exception If anything is unexpected
    468      */
    469     @Test
    470     public void defaultMatchesSuggested2() throws Exception {
    471         //       available     default          suggestion
    472         baseTest(              MIN_MARGINS[2],
    473                  MEDIA_SIZES,  MEDIA_SIZES[2],  MEDIA_SIZES[2],
    474                  // There are only two color modes, hence pick [1]
    475                  COLOR_MODES,  COLOR_MODES[1],  COLOR_MODES[1],
    476                  DUPLEX_MODES, DUPLEX_MODES[2], DUPLEX_MODES[2],
    477                  RESOLUTIONS,  RESOLUTIONS[2],  RESOLUTIONS[2]);
    478     }
    479 
    480     /**
    481      * Test that attributes are as expected if the no suggestion is given.
    482      *
    483      * This test sets the default attributes to the first selection.
    484      *
    485      * @throws Exception If anything is unexpected
    486      */
    487     @Test
    488     public void noSuggestion0() throws Exception {
    489         //       available     default          suggestion
    490         baseTest(              MIN_MARGINS[0],
    491                  MEDIA_SIZES,  MEDIA_SIZES[0],  null,
    492                  COLOR_MODES,  COLOR_MODES[0],  0,
    493                  DUPLEX_MODES, DUPLEX_MODES[0], 0,
    494                  RESOLUTIONS,  RESOLUTIONS[0],  null);
    495     }
    496 
    497     /**
    498      * Test that attributes are as expected if the no suggestion is given.
    499      *
    500      * This test sets the default attributes to the second selection.
    501      *
    502      * @throws Exception If anything is unexpected
    503      */
    504     @Test
    505     public void noSuggestion1() throws Exception {
    506         //       available     default          suggestion
    507         baseTest(              MIN_MARGINS[1],
    508                  MEDIA_SIZES,  MEDIA_SIZES[1],  null,
    509                  COLOR_MODES,  COLOR_MODES[1],  0,
    510                  DUPLEX_MODES, DUPLEX_MODES[1], 0,
    511                  RESOLUTIONS,  RESOLUTIONS[1],  null);
    512     }
    513 
    514     /**
    515      * Test that attributes are as expected if the no suggestion is given.
    516      *
    517      * This test sets the default attributes to the third selection.
    518      *
    519      * @throws Exception If anything is unexpected
    520      */
    521     @Test
    522     public void noSuggestion2() throws Exception {
    523         //       available     default          suggestion
    524         baseTest(              MIN_MARGINS[2],
    525                  MEDIA_SIZES,  MEDIA_SIZES[2],  null,
    526                  // There are only two color modes, hence pick [1]
    527                  COLOR_MODES,  COLOR_MODES[1],  0,
    528                  DUPLEX_MODES, DUPLEX_MODES[2], 0,
    529                  RESOLUTIONS,  RESOLUTIONS[2],  null);
    530     }
    531 
    532     /**
    533      * Test that attributes are as expected if only the {@link MediaSize} is suggested.
    534      *
    535      * This test sets the default attributes to the first selection, but the {@link MediaSize} is
    536      * suggested to be the second selection.
    537      *
    538      * @throws Exception If anything is unexpected
    539      */
    540     @Test
    541     public void mediaSizeSuggestion0() throws Exception {
    542         //       available     default          suggestion
    543         baseTest(              MIN_MARGINS[0],
    544                  MEDIA_SIZES,  MEDIA_SIZES[0],  MEDIA_SIZES[1],
    545                  COLOR_MODES,  COLOR_MODES[0],  0,
    546                  DUPLEX_MODES, DUPLEX_MODES[0], 0,
    547                  RESOLUTIONS,  RESOLUTIONS[0],  null);
    548     }
    549 
    550     /**
    551      * Test that attributes are as expected if only the {@link MediaSize} is suggested.
    552      *
    553      * This test sets the default attributes to the second selection, but the {@link MediaSize} is
    554      * suggested to be the first selection.
    555      *
    556      * @throws Exception If anything is unexpected
    557      */
    558     @Test
    559     public void mediaSizeSuggestion1() throws Exception {
    560         //       available     default          suggestion
    561         baseTest(              MIN_MARGINS[1],
    562                  MEDIA_SIZES,  MEDIA_SIZES[1],  MEDIA_SIZES[0],
    563                  COLOR_MODES,  COLOR_MODES[1],  0,
    564                  DUPLEX_MODES, DUPLEX_MODES[1], 0,
    565                  RESOLUTIONS,  RESOLUTIONS[1],  null);
    566     }
    567 
    568     /**
    569      * Test that attributes are as expected if only the duplex mode is suggested.
    570      *
    571      * This test sets the default attributes to the first selection, but the duplex mode is
    572      * suggested to be the second selection.
    573      *
    574      * @throws Exception If anything is unexpected
    575      */
    576     @Test
    577     public void duplexModeSuggestion0() throws Exception {
    578         //       available     default          suggestion
    579         baseTest(              MIN_MARGINS[0],
    580                  MEDIA_SIZES,  MEDIA_SIZES[0],  null,
    581                  COLOR_MODES,  COLOR_MODES[0],  0,
    582                  DUPLEX_MODES, DUPLEX_MODES[0], DUPLEX_MODES[1],
    583                  RESOLUTIONS,  RESOLUTIONS[0],  null);
    584     }
    585 
    586     /**
    587      * Test that attributes are as expected if only the duplex mode is suggested.
    588      *
    589      * This test sets the default attributes to the second selection, but the duplex mode is
    590      * suggested to be the first selection.
    591      *
    592      * @throws Exception If anything is unexpected
    593      */
    594     @Test
    595     public void duplexModeSuggestion1() throws Exception {
    596         //       available     default          suggestion
    597         baseTest(              MIN_MARGINS[1],
    598                  MEDIA_SIZES,  MEDIA_SIZES[1],  null,
    599                  COLOR_MODES,  COLOR_MODES[1],  0,
    600                  DUPLEX_MODES, DUPLEX_MODES[1], DUPLEX_MODES[0],
    601                  RESOLUTIONS,  RESOLUTIONS[1],  null);
    602     }
    603 
    604     /**
    605      * Test that attributes are as expected if all attributes are suggested and different from the
    606      * default attributes.
    607      *
    608      * @throws Exception If anything is unexpected
    609      */
    610     @Test
    611     public void suggestedDifferentFromDefault() throws Exception {
    612         //       available     default          suggestion
    613         baseTest(              MIN_MARGINS[0],
    614                  MEDIA_SIZES,  MEDIA_SIZES[0],  MEDIA_SIZES[1],
    615                  COLOR_MODES,  COLOR_MODES[0],  COLOR_MODES[1],
    616                  DUPLEX_MODES, DUPLEX_MODES[0], DUPLEX_MODES[1],
    617                  RESOLUTIONS,  RESOLUTIONS[0],  RESOLUTIONS[1]);
    618     }
    619 
    620     /**
    621      * Test that attributes are as expected if all attributes are suggested but all of them are not
    622      * supported by the printer.
    623      *
    624      * @throws Exception If anything is unexpected
    625      */
    626     @Test
    627     public void unsupportedSuggested() throws Exception {
    628         //       available                               default          suggestion
    629         baseTest(                                        MIN_MARGINS[0],
    630                  Arrays.copyOfRange(MEDIA_SIZES, 0, 1),  MEDIA_SIZES[0],  MEDIA_SIZES[1],
    631                  Arrays.copyOfRange(COLOR_MODES, 0, 1),  COLOR_MODES[0],  COLOR_MODES[1],
    632                  Arrays.copyOfRange(DUPLEX_MODES, 0, 1), DUPLEX_MODES[0], DUPLEX_MODES[1],
    633                  Arrays.copyOfRange(RESOLUTIONS, 0, 1),  RESOLUTIONS[0],  RESOLUTIONS[1]);
    634     }
    635 
    636     /**
    637      * Test that negative Margins do not cause issues in the print print spooler. Negative margins
    638      * are allowed because of historical reasons.
    639      *
    640      * @throws Exception If anything is unexpected
    641      */
    642     @Test
    643     public void negativeMargins() throws Exception {
    644         //       available     default                          suggestion
    645         baseTest(              new Margins(-10, -10, -10, -10),
    646                  MEDIA_SIZES,  MEDIA_SIZES[1],                  null,
    647                  COLOR_MODES,  COLOR_MODES[1],                  0,
    648                  DUPLEX_MODES, DUPLEX_MODES[1],                 0,
    649                  RESOLUTIONS,  RESOLUTIONS[1],                  null);
    650     }
    651 }
    652