]> granicus.if.org Git - icu/commitdiff
ICU-9240 Fixed a cloning problem in DecimalFormat which prevent formatToCharacterIter...
authorYoshito Umaoka <y.umaoka@gmail.com>
Thu, 3 May 2012 23:20:12 +0000 (23:20 +0000)
committerYoshito Umaoka <y.umaoka@gmail.com>
Thu, 3 May 2012 23:20:12 +0000 (23:20 +0000)
X-SVN-Rev: 31796

icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java

index b01587b4c3f73becb2fc44a978049206bd449cd0..bcfb7dd25e059c63496c60866e0b5f99d90e7179 100644 (file)
@@ -3508,6 +3508,7 @@ public class DecimalFormat extends NumberFormat {
             if (currencyPluralInfo != null) {
                 other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
             }
+            other.attributes = new ArrayList<FieldPosition>(); // #9240
 
             // TODO: We need to figure out whether we share a single copy of DigitList by
             // multiple cloned copies.  format/subformat are designed to use a single
index ed461fd0435401d98dd3a2d707a6feadc22de2a3..a161eb7c1b2558092c3b4afe8fe59d79baff55d0 100644 (file)
@@ -14,6 +14,7 @@
 package com.ibm.icu.dev.test.format;
 
 import java.math.BigInteger;
+import java.text.AttributedCharacterIterator;
 import java.text.FieldPosition;
 import java.text.ParseException;
 import java.text.ParsePosition;
@@ -2930,4 +2931,66 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             }
         }
     }
+
+    /*
+     * Test case for #9240
+     * ICU4J 49.1 DecimalFormat did not clone the internal object holding
+     * formatted text attribute information properly. Therefore, DecimalFormat
+     * created by cloning may return incorrect results or may throw an exception
+     * when formatToCharacterIterator is invoked from multiple threads.
+     */
+    public void TestFormatToCharacterIteratorThread() {
+        final int COUNT = 10;
+
+        DecimalFormat fmt1 = new DecimalFormat("#0");
+        DecimalFormat fmt2 = (DecimalFormat)fmt1.clone();
+
+        int[] res1 = new int[COUNT];
+        int[] res2 = new int[COUNT];
+
+        Thread t1 = new Thread(new FormatCharItrTestThread(fmt1, 1, res1));
+        Thread t2 = new Thread(new FormatCharItrTestThread(fmt2, 100, res2));
+
+        t1.start();
+        t2.start();
+
+        try {
+            t1.join();
+            t2.join();
+        } catch (InterruptedException e) {
+            //TODO
+        }
+
+        int val1 = res1[0];
+        int val2 = res2[0];
+
+        for (int i = 0; i < COUNT; i++) {
+            if (res1[i] != val1) {
+                errln("Inconsistent first run limit in test thread 1");
+            }
+            if (res2[i] != val2) {
+                errln("Inconsistent first run limit in test thread 2");
+            }
+        }
+    }
+
+    private static class FormatCharItrTestThread implements Runnable {
+        private NumberFormat fmt;
+        private int num;
+        private int[] result;
+
+        FormatCharItrTestThread(NumberFormat fmt, int num, int[] result) {
+            this.fmt = fmt;
+            this.num = num;
+            this.result = result;
+        }
+
+        public void run() {
+            for (int i = 0; i < result.length; i++) {
+                AttributedCharacterIterator acitr = fmt.formatToCharacterIterator(num);
+                acitr.first();
+                result[i] = acitr.getRunLimit();
+            }
+        }
+    }
 }