|
| 1 | +package org.json.junit.milestone5; |
| 2 | + |
| 3 | +import org.json.JSONArray; |
| 4 | +import org.json.JSONObject; |
| 5 | +import org.json.XML; |
| 6 | +import org.junit.Test; |
| 7 | + |
| 8 | +import java.io.Reader; |
| 9 | +import java.io.StringReader; |
| 10 | +import java.util.concurrent.CountDownLatch; |
| 11 | +import java.util.concurrent.Future; |
| 12 | +import java.util.concurrent.TimeUnit; |
| 13 | + |
| 14 | +import static org.junit.Assert.*; |
| 15 | + |
| 16 | +public class JSONObjectAsyncTest { |
| 17 | + |
| 18 | + private final XML.AsyncRunner runner = new XML.AsyncRunner(); |
| 19 | + |
| 20 | + public JSONObjectAsyncTest() { |
| 21 | + // Default constructor |
| 22 | + } |
| 23 | + |
| 24 | + private final Reader medReader = new StringReader( |
| 25 | + "<catalog>" |
| 26 | + + " <book id=\"bk101\">" |
| 27 | + + " <author>Gambardella, Matthew</author>" |
| 28 | + + " <title>XML Developer's Guide</title>" |
| 29 | + + " <genre>Computer</genre>" |
| 30 | + + " <price>44.95</price>" |
| 31 | + + " <publish_date>2000-10-01</publish_date>" |
| 32 | + + " <description>An in-depth look at creating applications with XML.</description>" |
| 33 | + + " </book>" |
| 34 | + + " <book id=\"bk102\">" |
| 35 | + + " <author>Ralls, Kim</author>" |
| 36 | + + " <title>Midnight Rain</title>" |
| 37 | + + " <genre>Fantasy</genre>" |
| 38 | + + " <price>5.95</price>" |
| 39 | + + " <publish_date>2000-12-16</publish_date>" |
| 40 | + + " <description>A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.</description>" |
| 41 | + + " </book>" |
| 42 | + + "</catalog>" |
| 43 | + ); |
| 44 | + |
| 45 | + private final Reader smallReader = new StringReader( |
| 46 | + "<root>" |
| 47 | + + " <message>Hello</message>" |
| 48 | + + "</root>" |
| 49 | + ); |
| 50 | + |
| 51 | + @Test |
| 52 | + public void testAsyncParsing() throws Exception { |
| 53 | + CountDownLatch latch = new CountDownLatch(2); |
| 54 | + JSONObject[] results = new JSONObject[2]; |
| 55 | + Exception[] errors = new Exception[2]; |
| 56 | + long[] timeElapsed = new long[2]; |
| 57 | + |
| 58 | + final long startTime = System.nanoTime(); |
| 59 | + |
| 60 | + Future<JSONObject> task1 = XML.toJSONObject( |
| 61 | + medReader, |
| 62 | + jo -> { |
| 63 | + results[0] = jo; |
| 64 | + long endNano = System.nanoTime(); |
| 65 | + timeElapsed[0] = TimeUnit.NANOSECONDS.toMillis(endNano - startTime); |
| 66 | + latch.countDown(); |
| 67 | + }, |
| 68 | + e -> { |
| 69 | + errors[0] = e; |
| 70 | + latch.countDown(); |
| 71 | + } |
| 72 | + ); |
| 73 | + |
| 74 | + Future<JSONObject> task2 = XML.toJSONObject( |
| 75 | + smallReader, |
| 76 | + jo -> { |
| 77 | + results[1] = jo; |
| 78 | + long endNano = System.nanoTime(); |
| 79 | + timeElapsed[1] = TimeUnit.NANOSECONDS.toMillis(endNano - startTime); |
| 80 | + latch.countDown(); |
| 81 | + }, |
| 82 | + e -> { |
| 83 | + errors[1] = e; |
| 84 | + latch.countDown(); |
| 85 | + } |
| 86 | + ); |
| 87 | + |
| 88 | + boolean completed = latch.await(10, TimeUnit.SECONDS); |
| 89 | + assertTrue("Both callbacks should complete within 10 seconds", completed); |
| 90 | + |
| 91 | + assertNull("No error expected for medReader", errors[0]); |
| 92 | + assertNull("No error expected for smallReader", errors[1]); |
| 93 | + |
| 94 | + JSONObject expectedMed = new JSONObject() |
| 95 | + .put("catalog", new JSONObject() |
| 96 | + .put("book", new JSONArray() |
| 97 | + .put(new JSONObject() |
| 98 | + .put("author", "Gambardella, Matthew") |
| 99 | + .put("title", "XML Developer's Guide") |
| 100 | + .put("genre", "Computer") |
| 101 | + .put("price", 44.95) |
| 102 | + .put("publish_date", "2000-10-01") |
| 103 | + .put("description", "An in-depth look at creating applications with XML.") |
| 104 | + .put("id", "bk101") |
| 105 | + ) |
| 106 | + .put(new JSONObject() |
| 107 | + .put("author", "Ralls, Kim") |
| 108 | + .put("title", "Midnight Rain") |
| 109 | + .put("genre", "Fantasy") |
| 110 | + .put("price", 5.95) |
| 111 | + .put("publish_date", "2000-12-16") |
| 112 | + .put("description", "A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.") |
| 113 | + .put("id", "bk102") |
| 114 | + ) |
| 115 | + ) |
| 116 | + ); |
| 117 | + |
| 118 | + JSONObject expectedSmall = new JSONObject() |
| 119 | + .put("root", new JSONObject() |
| 120 | + .put("message", "Hello") |
| 121 | + ); |
| 122 | + |
| 123 | + assertTrue("medReader JSON should match expected", expectedMed.similar(results[0])); |
| 124 | + assertTrue("smallReader JSON should match expected", expectedSmall.similar(results[1])); |
| 125 | + |
| 126 | + assertTrue("smallReader must be faster than medReader", timeElapsed[1] < timeElapsed[0]); |
| 127 | + |
| 128 | + // Optional debug output |
| 129 | + System.out.println("medReader elapsed: " + timeElapsed[0] + " ms"); |
| 130 | + System.out.println("smallReader elapsed: " + timeElapsed[1] + " ms"); |
| 131 | + } |
| 132 | + |
| 133 | + @Test |
| 134 | + public void testAsyncParsingWithInvalidXML() throws Exception { |
| 135 | + CountDownLatch latch = new CountDownLatch(1); |
| 136 | + Exception[] errors = new Exception[1]; |
| 137 | + |
| 138 | + Reader invalidReader = new StringReader( |
| 139 | + "<root><tag>Unclosed tag</root>" |
| 140 | + ); |
| 141 | + |
| 142 | + Future<JSONObject> task = org.json.XML.toJSONObject( |
| 143 | + invalidReader, |
| 144 | + jo -> fail("Should not succeed with invalid XML"), |
| 145 | + e -> { |
| 146 | + errors[0] = e; |
| 147 | + latch.countDown(); |
| 148 | + } |
| 149 | + ); |
| 150 | + |
| 151 | + boolean completed = latch.await(5, TimeUnit.SECONDS); |
| 152 | + assertTrue("Callback should complete within 5 seconds", completed); |
| 153 | + assertNotNull("Error should be captured for invalid XML", errors[0]); |
| 154 | + assertTrue("Error should be a JSONException", errors[0] instanceof org.json.JSONException); |
| 155 | + } |
| 156 | + |
| 157 | +} |
0 commit comments