Home | History | Annotate | Download | only in nio
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.harmony.tests.java.nio;
     19 
     20 import java.nio.BufferOverflowException;
     21 import java.nio.BufferUnderflowException;
     22 import java.nio.ByteOrder;
     23 import java.nio.DoubleBuffer;
     24 import java.nio.FloatBuffer;
     25 import java.nio.InvalidMarkException;
     26 
     27 /**
     28  * Tests java.nio.FloatBuffer
     29  *
     30  */
     31 public class FloatBufferTest extends AbstractBufferTest {
     32 
     33     protected static final int SMALL_TEST_LENGTH = 5;
     34 
     35     protected static final int BUFFER_LENGTH = 20;
     36 
     37     protected FloatBuffer buf;
     38 
     39     protected void setUp() throws Exception {
     40         buf = FloatBuffer.allocate(BUFFER_LENGTH);
     41         loadTestData1(buf);
     42         baseBuf = buf;
     43     }
     44 
     45     protected void tearDown() throws Exception {
     46         buf = null;
     47         baseBuf = null;
     48     }
     49 
     50     public void testArray() {
     51         float array[] = buf.array();
     52         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     53 
     54         loadTestData1(array, buf.arrayOffset(), buf.capacity());
     55         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     56 
     57         loadTestData2(array, buf.arrayOffset(), buf.capacity());
     58         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     59 
     60         loadTestData1(buf);
     61         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     62 
     63         loadTestData2(buf);
     64         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     65     }
     66 
     67     public void testArrayOffset() {
     68         float array[] = buf.array();
     69         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     70 
     71         loadTestData1(array, buf.arrayOffset(), buf.capacity());
     72         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     73 
     74         loadTestData2(array, buf.arrayOffset(), buf.capacity());
     75         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     76 
     77         loadTestData1(buf);
     78         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     79 
     80         loadTestData2(buf);
     81         assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
     82     }
     83 
     84     public void testAsReadOnlyBuffer() {
     85         buf.clear();
     86         buf.mark();
     87         buf.position(buf.limit());
     88 
     89         // readonly's contents should be the same as buf
     90         FloatBuffer readonly = buf.asReadOnlyBuffer();
     91         assertNotSame(buf, readonly);
     92         assertTrue(readonly.isReadOnly());
     93         assertEquals(buf.position(), readonly.position());
     94         assertEquals(buf.limit(), readonly.limit());
     95         assertEquals(buf.isDirect(), readonly.isDirect());
     96         assertEquals(buf.order(), readonly.order());
     97         assertContentEquals(buf, readonly);
     98 
     99         // readonly's position, mark, and limit should be independent to buf
    100         readonly.reset();
    101         assertEquals(readonly.position(), 0);
    102         readonly.clear();
    103         assertEquals(buf.position(), buf.limit());
    104         buf.reset();
    105         assertEquals(buf.position(), 0);
    106     }
    107 
    108     public void testCompact() {
    109 
    110         // case: buffer is full
    111         buf.clear();
    112         buf.mark();
    113         loadTestData1(buf);
    114         FloatBuffer ret = buf.compact();
    115         assertSame(ret, buf);
    116         assertEquals(buf.position(), buf.capacity());
    117         assertEquals(buf.limit(), buf.capacity());
    118         assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
    119         try {
    120             buf.reset();
    121             fail("Should throw Exception"); //$NON-NLS-1$
    122         } catch (InvalidMarkException e) {
    123             // expected
    124         }
    125 
    126         // case: buffer is empty
    127         buf.position(0);
    128         buf.limit(0);
    129         buf.mark();
    130         ret = buf.compact();
    131         assertSame(ret, buf);
    132         assertEquals(buf.position(), 0);
    133         assertEquals(buf.limit(), buf.capacity());
    134         assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
    135         try {
    136             buf.reset();
    137             fail("Should throw Exception"); //$NON-NLS-1$
    138         } catch (InvalidMarkException e) {
    139             // expected
    140         }
    141 
    142         // case: normal
    143         assertTrue(buf.capacity() > 5);
    144         buf.position(1);
    145         buf.limit(5);
    146         buf.mark();
    147         ret = buf.compact();
    148         assertSame(ret, buf);
    149         assertEquals(buf.position(), 4);
    150         assertEquals(buf.limit(), buf.capacity());
    151         assertContentLikeTestData1(buf, 0, 1.0f, 4);
    152         try {
    153             buf.reset();
    154             fail("Should throw Exception"); //$NON-NLS-1$
    155         } catch (InvalidMarkException e) {
    156             // expected
    157         }
    158     }
    159 
    160     public void testCompareTo() {
    161         try {
    162             buf.compareTo(null);
    163             fail("Should throw NPE");
    164         } catch (NullPointerException e) {
    165             // expected
    166         }
    167 
    168         // compare to self
    169         assertEquals(0, buf.compareTo(buf));
    170 
    171         // normal cases
    172         assertTrue(buf.capacity() > 5);
    173         buf.clear();
    174         FloatBuffer other = FloatBuffer.allocate(buf.capacity());
    175         loadTestData1(other);
    176         assertEquals(0, buf.compareTo(other));
    177         assertEquals(0, other.compareTo(buf));
    178         buf.position(1);
    179         assertTrue(buf.compareTo(other) > 0);
    180         assertTrue(other.compareTo(buf) < 0);
    181         other.position(2);
    182         assertTrue(buf.compareTo(other) < 0);
    183         assertTrue(other.compareTo(buf) > 0);
    184         buf.position(2);
    185         other.limit(5);
    186         assertTrue(buf.compareTo(other) > 0);
    187         assertTrue(other.compareTo(buf) < 0);
    188 
    189         FloatBuffer fbuffer1 = FloatBuffer.wrap(new float[] { Float.NaN });
    190         FloatBuffer fbuffer2 = FloatBuffer.wrap(new float[] { Float.NaN });
    191         FloatBuffer fbuffer3 = FloatBuffer.wrap(new float[] { 42f });
    192 
    193         assertEquals("Failed equal comparison with NaN entry", 0, fbuffer1
    194                 .compareTo(fbuffer2));
    195         assertEquals("Failed greater than comparison with NaN entry", -1, fbuffer3
    196                 .compareTo(fbuffer1));
    197         assertEquals("Failed greater than comparison with NaN entry", 1, fbuffer1
    198                 .compareTo(fbuffer3));
    199 
    200     }
    201 
    202     public void testDuplicate() {
    203         buf.clear();
    204         buf.mark();
    205         buf.position(buf.limit());
    206 
    207         // duplicate's contents should be the same as buf
    208         FloatBuffer duplicate = buf.duplicate();
    209         assertNotSame(buf, duplicate);
    210         assertEquals(buf.position(), duplicate.position());
    211         assertEquals(buf.limit(), duplicate.limit());
    212         assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
    213         assertEquals(buf.isDirect(), duplicate.isDirect());
    214         assertEquals(buf.order(), duplicate.order());
    215         assertContentEquals(buf, duplicate);
    216 
    217         // duplicate's position, mark, and limit should be independent to buf
    218         duplicate.reset();
    219         assertEquals(duplicate.position(), 0);
    220         duplicate.clear();
    221         assertEquals(buf.position(), buf.limit());
    222         buf.reset();
    223         assertEquals(buf.position(), 0);
    224 
    225         // duplicate share the same content with buf
    226         if (!duplicate.isReadOnly()) {
    227             loadTestData1(buf);
    228             assertContentEquals(buf, duplicate);
    229             loadTestData2(duplicate);
    230             assertContentEquals(buf, duplicate);
    231         }
    232     }
    233 
    234     public void testEquals() {
    235         // equal to self
    236         assertTrue(buf.equals(buf));
    237         FloatBuffer readonly = buf.asReadOnlyBuffer();
    238         assertTrue(buf.equals(readonly));
    239         FloatBuffer duplicate = buf.duplicate();
    240         assertTrue(buf.equals(duplicate));
    241 
    242         // always false, if type mismatch
    243         assertFalse(buf.equals(Boolean.TRUE));
    244 
    245         assertTrue(buf.capacity() > 5);
    246 
    247         buf.limit(buf.capacity()).position(0);
    248         readonly.limit(readonly.capacity()).position(1);
    249         assertFalse(buf.equals(readonly));
    250 
    251         buf.limit(buf.capacity() - 1).position(0);
    252         duplicate.limit(duplicate.capacity()).position(0);
    253         assertFalse(buf.equals(duplicate));
    254     }
    255 
    256     /*
    257      * Class under test for float get()
    258      */
    259     public void testGet() {
    260         buf.clear();
    261         for (int i = 0; i < buf.capacity(); i++) {
    262             assertEquals(buf.position(), i);
    263             assertEquals(buf.get(), buf.get(i), 0.01);
    264         }
    265         try {
    266             buf.get();
    267             fail("Should throw Exception"); //$NON-NLS-1$
    268         } catch (BufferUnderflowException e) {
    269             // expected
    270         }
    271     }
    272 
    273     /*
    274      * Class under test for java.nio.FloatBuffer get(float[])
    275      */
    276     public void testGetfloatArray() {
    277         float array[] = new float[1];
    278         buf.clear();
    279         for (int i = 0; i < buf.capacity(); i++) {
    280             assertEquals(buf.position(), i);
    281             FloatBuffer ret = buf.get(array);
    282             assertEquals(array[0], buf.get(i), 0.01);
    283             assertSame(ret, buf);
    284         }
    285         try {
    286             buf.get(array);
    287             fail("Should throw Exception"); //$NON-NLS-1$
    288         } catch (BufferUnderflowException e) {
    289             // expected
    290         }
    291         try {
    292             buf.position(buf.limit());
    293             buf.get((float[])null);
    294             fail("Should throw Exception"); //$NON-NLS-1$
    295         } catch (NullPointerException e) {
    296             // expected
    297         }
    298         buf.get(new float[0]);
    299     }
    300 
    301     /*
    302      * Class under test for java.nio.FloatBuffer get(float[], int, int)
    303      */
    304     public void testGetfloatArrayintint() {
    305         buf.clear();
    306         float array[] = new float[buf.capacity()];
    307 
    308         try {
    309             buf.get(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
    310             fail("Should throw Exception"); //$NON-NLS-1$
    311         } catch (BufferUnderflowException e) {
    312             // expected
    313         }
    314         assertEquals(buf.position(), 0);
    315         try {
    316             buf.get(array, -1, array.length);
    317             fail("Should throw Exception"); //$NON-NLS-1$
    318         } catch (IndexOutOfBoundsException e) {
    319             // expected
    320         }
    321         buf.get(array, array.length, 0);
    322         try {
    323             buf.get(array, array.length + 1, 1);
    324             fail("Should throw Exception"); //$NON-NLS-1$
    325         } catch (IndexOutOfBoundsException e) {
    326             // expected
    327         }
    328         assertEquals(buf.position(), 0);
    329         try {
    330             buf.get(array, 2, -1);
    331             fail("Should throw Exception"); //$NON-NLS-1$
    332         } catch (IndexOutOfBoundsException e) {
    333             // expected
    334         }
    335         try {
    336             buf.get((float[])null, 2, -1);
    337             fail("Should throw Exception"); //$NON-NLS-1$
    338         } catch (NullPointerException e) {
    339             // expected
    340         }
    341         try {
    342             buf.get(array, 2, array.length);
    343             fail("Should throw Exception"); //$NON-NLS-1$
    344         } catch (IndexOutOfBoundsException e) {
    345             // expected
    346         }
    347         try {
    348             buf.get(array, 1, Integer.MAX_VALUE);
    349             fail("Should throw Exception"); //$NON-NLS-1$
    350         } catch (BufferUnderflowException expected) {
    351         } catch (IndexOutOfBoundsException expected) {
    352         }
    353         try {
    354             buf.get(array, Integer.MAX_VALUE, 1);
    355             fail("Should throw Exception"); //$NON-NLS-1$
    356         } catch (IndexOutOfBoundsException e) {
    357             // expected
    358         }
    359         assertEquals(buf.position(), 0);
    360 
    361         buf.clear();
    362         FloatBuffer ret = buf.get(array, 0, array.length);
    363         assertEquals(buf.position(), buf.capacity());
    364         assertContentEquals(buf, array, 0, array.length);
    365         assertSame(ret, buf);
    366     }
    367 
    368     /*
    369      * Class under test for float get(int)
    370      */
    371     public void testGetint() {
    372         buf.clear();
    373         for (int i = 0; i < buf.capacity(); i++) {
    374             assertEquals(buf.position(), i);
    375             assertEquals(buf.get(), buf.get(i), 0.01);
    376         }
    377         try {
    378             buf.get(-1);
    379             fail("Should throw Exception"); //$NON-NLS-1$
    380         } catch (IndexOutOfBoundsException e) {
    381             // expected
    382         }
    383         try {
    384             buf.get(buf.limit());
    385             fail("Should throw Exception"); //$NON-NLS-1$
    386         } catch (IndexOutOfBoundsException e) {
    387             // expected
    388         }
    389     }
    390 
    391     public void testHasArray() {
    392         assertNotNull(buf.array());
    393     }
    394 
    395     public void testHashCode() {
    396         buf.clear();
    397         FloatBuffer readonly = buf.asReadOnlyBuffer();
    398         FloatBuffer duplicate = buf.duplicate();
    399         assertTrue(buf.hashCode() == readonly.hashCode());
    400 
    401         assertTrue(buf.capacity() > 5);
    402         duplicate.position(buf.capacity() / 2);
    403         assertTrue(buf.hashCode() != duplicate.hashCode());
    404     }
    405 
    406     public void testIsDirect() {
    407         assertFalse(buf.isDirect());
    408     }
    409 
    410     public void testOrder() {
    411         buf.order();
    412         if (buf.hasArray()) {
    413             assertEquals(ByteOrder.nativeOrder(), buf.order());
    414         }
    415     }
    416 
    417     /*
    418      * Class under test for java.nio.FloatBuffer put(float)
    419      */
    420     public void testPutfloat() {
    421         buf.clear();
    422         for (int i = 0; i < buf.capacity(); i++) {
    423             assertEquals(buf.position(), i);
    424             FloatBuffer ret = buf.put((float) i);
    425             assertEquals(buf.get(i), (float) i, 0.0);
    426             assertSame(ret, buf);
    427         }
    428         try {
    429             buf.put(0);
    430             fail("Should throw Exception"); //$NON-NLS-1$
    431         } catch (BufferOverflowException e) {
    432             // expected
    433         }
    434     }
    435 
    436     /*
    437      * Class under test for java.nio.FloatBuffer put(float[])
    438      */
    439     public void testPutfloatArray() {
    440         float array[] = new float[1];
    441         buf.clear();
    442         for (int i = 0; i < buf.capacity(); i++) {
    443             assertEquals(buf.position(), i);
    444             array[0] = (float) i;
    445             FloatBuffer ret = buf.put(array);
    446             assertEquals(buf.get(i), (float) i, 0.0);
    447             assertSame(ret, buf);
    448         }
    449         try {
    450             buf.put(array);
    451             fail("Should throw Exception"); //$NON-NLS-1$
    452         } catch (BufferOverflowException e) {
    453             // expected
    454         }
    455         try {
    456             buf.position(buf.limit());
    457             buf.put((float[])null);
    458             fail("Should throw Exception"); //$NON-NLS-1$
    459         } catch (NullPointerException e) {
    460             // expected
    461         }
    462     }
    463 
    464     /*
    465      * Class under test for java.nio.FloatBuffer put(float[], int, int)
    466      */
    467     public void testPutfloatArrayintint() {
    468         buf.clear();
    469         float array[] = new float[buf.capacity()];
    470         try {
    471             buf.put(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
    472             fail("Should throw Exception"); //$NON-NLS-1$
    473         } catch (BufferOverflowException e) {
    474             // expected
    475         }
    476         assertEquals(buf.position(), 0);
    477         try {
    478             buf.put(array, -1, array.length);
    479             fail("Should throw Exception"); //$NON-NLS-1$
    480         } catch (IndexOutOfBoundsException e) {
    481             // expected
    482         }
    483         try {
    484             buf.put(array, array.length + 1, 0);
    485             fail("Should throw Exception"); //$NON-NLS-1$
    486         } catch (IndexOutOfBoundsException e) {
    487             // expected
    488         }
    489         buf.put(array, array.length, 0);
    490         assertEquals(buf.position(), 0);
    491         try {
    492             buf.put(array, 0, -1);
    493             fail("Should throw Exception"); //$NON-NLS-1$
    494         } catch (IndexOutOfBoundsException e) {
    495             // expected
    496         }
    497         try {
    498             buf.put((float[])null, 0, -1);
    499             fail("Should throw Exception"); //$NON-NLS-1$
    500         } catch (NullPointerException e) {
    501             // expected
    502         }
    503         try {
    504             buf.put(array, 2, array.length);
    505             fail("Should throw Exception"); //$NON-NLS-1$
    506         } catch (IndexOutOfBoundsException e) {
    507             // expected
    508         }
    509         try {
    510             buf.put(array, Integer.MAX_VALUE, 1);
    511             fail("Should throw Exception"); //$NON-NLS-1$
    512         } catch (IndexOutOfBoundsException e) {
    513             // expected
    514         }
    515         try {
    516             buf.put(array, 1, Integer.MAX_VALUE);
    517             fail("Should throw Exception"); //$NON-NLS-1$
    518         } catch (BufferOverflowException expected) {
    519         } catch (IndexOutOfBoundsException expected) {
    520         }
    521         assertEquals(buf.position(), 0);
    522 
    523         loadTestData2(array, 0, array.length);
    524         FloatBuffer ret = buf.put(array, 0, array.length);
    525         assertEquals(buf.position(), buf.capacity());
    526         assertContentEquals(buf, array, 0, array.length);
    527         assertSame(ret, buf);
    528     }
    529 
    530     /*
    531      * Class under test for java.nio.FloatBuffer put(java.nio.FloatBuffer)
    532      */
    533     public void testPutFloatBuffer() {
    534         FloatBuffer other = FloatBuffer.allocate(buf.capacity());
    535         try {
    536             buf.put(buf);
    537             fail("Should throw Exception"); //$NON-NLS-1$
    538         } catch (IllegalArgumentException e) {
    539             // expected
    540         }
    541         try {
    542             buf.put(FloatBuffer.allocate(buf.capacity() + 1));
    543             fail("Should throw Exception"); //$NON-NLS-1$
    544         } catch (BufferOverflowException e) {
    545             // expected
    546         }
    547         try {
    548             buf.flip();
    549             buf.put((FloatBuffer)null);
    550             fail("Should throw Exception"); //$NON-NLS-1$
    551         } catch (NullPointerException e) {
    552             // expected
    553         }
    554         buf.clear();
    555         loadTestData2(other);
    556         other.clear();
    557         buf.clear();
    558         FloatBuffer ret = buf.put(other);
    559         assertEquals(other.position(), other.capacity());
    560         assertEquals(buf.position(), buf.capacity());
    561         assertContentEquals(other, buf);
    562         assertSame(ret, buf);
    563     }
    564 
    565     /*
    566      * Class under test for java.nio.FloatBuffer put(int, float)
    567      */
    568     public void testPutintfloat() {
    569         buf.clear();
    570         for (int i = 0; i < buf.capacity(); i++) {
    571             assertEquals(buf.position(), 0);
    572             FloatBuffer ret = buf.put(i, (float) i);
    573             assertEquals(buf.get(i), (float) i, 0.0);
    574             assertSame(ret, buf);
    575         }
    576         try {
    577             buf.put(-1, 0);
    578             fail("Should throw Exception"); //$NON-NLS-1$
    579         } catch (IndexOutOfBoundsException e) {
    580             // expected
    581         }
    582         try {
    583             buf.put(buf.limit(), 0);
    584             fail("Should throw Exception"); //$NON-NLS-1$
    585         } catch (IndexOutOfBoundsException e) {
    586             // expected
    587         }
    588     }
    589 
    590     public void testSlice() {
    591         assertTrue(buf.capacity() > 5);
    592         buf.position(1);
    593         buf.limit(buf.capacity() - 1);
    594 
    595         FloatBuffer slice = buf.slice();
    596         assertEquals(buf.isReadOnly(), slice.isReadOnly());
    597         assertEquals(buf.isDirect(), slice.isDirect());
    598         assertEquals(buf.order(), slice.order());
    599         assertEquals(slice.position(), 0);
    600         assertEquals(slice.limit(), buf.remaining());
    601         assertEquals(slice.capacity(), buf.remaining());
    602         try {
    603             slice.reset();
    604             fail("Should throw Exception"); //$NON-NLS-1$
    605         } catch (InvalidMarkException e) {
    606             // expected
    607         }
    608 
    609         // slice share the same content with buf
    610         if (!slice.isReadOnly()) {
    611             loadTestData1(slice);
    612             assertContentLikeTestData1(buf, 1, 0, slice.capacity());
    613             buf.put(2, 500);
    614             assertEquals(slice.get(1), 500, 0.0);
    615         }
    616     }
    617 
    618     public void testToString() {
    619         String str = buf.toString();
    620         assertTrue(str.indexOf("Float") >= 0 || str.indexOf("float") >= 0);
    621         assertTrue(str.indexOf("" + buf.position()) >= 0);
    622         assertTrue(str.indexOf("" + buf.limit()) >= 0);
    623         assertTrue(str.indexOf("" + buf.capacity()) >= 0);
    624     }
    625 
    626     void loadTestData1(float array[], int offset, int length) {
    627         for (int i = 0; i < length; i++) {
    628             array[offset + i] = (float) i;
    629         }
    630     }
    631 
    632     void loadTestData2(float array[], int offset, int length) {
    633         for (int i = 0; i < length; i++) {
    634             array[offset + i] = (float) length - i;
    635         }
    636     }
    637 
    638     void loadTestData1(FloatBuffer buf) {
    639         buf.clear();
    640         for (int i = 0; i < buf.capacity(); i++) {
    641             buf.put(i, (float) i);
    642         }
    643     }
    644 
    645     void loadTestData2(FloatBuffer buf) {
    646         buf.clear();
    647         for (int i = 0; i < buf.capacity(); i++) {
    648             buf.put(i, (float) buf.capacity() - i);
    649         }
    650     }
    651 
    652     void assertContentEquals(FloatBuffer buf, float array[],
    653             int offset, int length) {
    654         for (int i = 0; i < length; i++) {
    655             assertEquals(buf.get(i), array[offset + i], 0.01);
    656         }
    657     }
    658 
    659     void assertContentEquals(FloatBuffer buf, FloatBuffer other) {
    660         assertEquals(buf.capacity(), other.capacity());
    661         for (int i = 0; i < buf.capacity(); i++) {
    662             assertEquals(buf.get(i), other.get(i), 0.01);
    663         }
    664     }
    665 
    666     void assertContentLikeTestData1(FloatBuffer buf,
    667             int startIndex, float startValue, int length) {
    668         float value = startValue;
    669         for (int i = 0; i < length; i++) {
    670             assertEquals(buf.get(startIndex + i), value, 0.01);
    671             value = value + 1.0f;
    672         }
    673     }
    674 }
    675