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