Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Saturn225
Copy link
Contributor

@Saturn225 Saturn225 commented Nov 8, 2024

                at zio.test.TestArrow$Span.substring(TestArrow.scala:291)

Here the error arised because the Span.substring in TestArrow.scala throws an IndexOutOfBoundsException when the specified start and end values exceed the length of the target string. This issue affects the rendering of error messages for failed assertions. To fix this behaviour seen I have added clamping for out-of-bounds start and end indices in Span substring and tests to verify for the same

/claim #9209

@algora-pbc
Copy link

algora-pbc bot commented Nov 8, 2024

💵 To receive payouts, sign up on Algora, link your Github account and connect with Stripe.

Copy link
Contributor

@kyri-petrou kyri-petrou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Saturn225, thanks for the contribution. Could you please include the test that was included in the linked issue to ensure that it solves the issue?

@Saturn225
Copy link
Contributor Author

Saturn225 commented Nov 9, 2024

@kyri-petrou @Kalin-Rudnicki Is it to use izumi-reflect / scala-reflect of the reproducer in the issue mentioned
PS: I am not much aware of this libraries :)

@Saturn225
Copy link
Contributor Author

Saturn225 commented Nov 9, 2024

But I have reproduced to reflect the same for reproduce StringIndexOutOfBoundsException

  suite("Span substring bounds")(
    test("correctly handles valid span bounds within string length") {
      val span = Span(0, 3)
      assertTrue(span.substring("foo bar baz") == "foo")
    },
    test("handles span start out of bounds on the negative side") {
      val span = Span(-20, 5)
      assertTrue(span.substring("foo bar baz") == "foo b")
    },
    test("handles span end beyond string length") {
      val span = Span(0, 100)
      assertTrue(span.substring("foo") == "foo")
    },
    test("clamps both start and end when both are out of bounds") {
      val span = Span(-50, 200)
      assertTrue(span.substring("foo") == "foo")
    },
    test("returns empty string when start equals end") {
      val span = Span(3, 3)
      assertTrue(span.substring("foo bar baz") == "")
    },
    test("returns empty string when start is greater than end") {
      val span = Span(10, 5)
      assertTrue(span.substring("foo bar baz") == "")
    }
  )
  
  + Span substring bounds
    + correctly handles valid span bounds within string length - 3 ms
    - clamps both start and end when both are out of bounds - 3 ms
      ✗ ERROR: java.lang.StringIndexOutOfBoundsException: Range [-50, 200) out of bounds for length 3
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
        java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
        java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromToIndex(Preconditions.java:112)
        java.base/jdk.internal.util.Preconditions.checkFromToIndex(Preconditions.java:349)
        java.base/java.lang.String.checkBoundsBeginEnd(String.java:4865)
        java.base/java.lang.String.substring(String.java:2834)
      span.substring("baz") == "baz"
      span = Span(
        start = -50,
        end = 200
      )
      at /home/runner/work/zio/zio/test-tests/shared/src/test/scala/zio/test/TestArrowSpec.scala:163 
    - clamps end when it exceeds string length - 12 ms
      ✗ ERROR: java.lang.StringIndexOutOfBoundsException: Range [0, 100) out of bounds for length 3
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
        java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
        java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromToIndex(Preconditions.java:112)
        java.base/jdk.internal.util.Preconditions.checkFromToIndex(Preconditions.java:349)
        java.base/java.lang.String.checkBoundsBeginEnd(String.java:[4865](https://github.com/varshith257/zio/actions/runs/11758671362/job/32757291277#step:5:4865))
        java.base/java.lang.String.substring(String.java:2834)
      span.substring("foo") == "foo"
      span = Span(
        start = 0,
        end = 100
      )
      at /home/runner/work/zio/zio/test-tests/shared/src/test/scala/zio/test/TestArrowSpec.scala:159 
    - clamps start when it is out of bounds - 13 ms
      ✗ ERROR: java.lang.StringIndexOutOfBoundsException: Range [-20, 5) out of bounds for length 11
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
        java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
        java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromToIndex(Preconditions.java:112)
        java.base/jdk.internal.util.Preconditions.checkFromToIndex(Preconditions.java:349)
        java.base/java.lang.String.checkBoundsBeginEnd(String.java:4865)
        java.base/java.lang.String.substring(String.java:2834)
      span.substring("foo bar baz") == "foo b"
      span = Span(
        start = -20,
        end = 5
      )
      at /home/runner/work/zio/zio/test-tests/shared/src/test/scala/zio/test/TestArrowSpec.scala:155 
    + returns empty string when start equals end - 545314 ns
    - returns empty string when start is greater than end - 16 ms
      ✗ ERROR: java.lang.StringIndexOutOfBoundsException: Range [10, 5) out of bounds for length 11
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
        java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
        java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
        java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
        java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromToIndex(Preconditions.java:112)
        java.base/jdk.internal.util.Preconditions.checkFromToIndex(Preconditions.java:349)
        java.base/java.lang.String.checkBoundsBeginEnd(String.java:4865)
        java.base/java.lang.String.substring(String.java:2834)
      span.substring("foo bar baz") == ""
      span = Span(
        start = 10,
        end = 5
      )

and this patch worked fine!

Copy link
Contributor

@kyri-petrou kyri-petrou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Saturn225 I think there is likely a more fundamental problem which is the incorrect calculation of bounds in the Span. Although given that the reproducer in the linked issue is not really straightforward (I'm actually not sure what those objects / classes come from) and that a "proper" fix would require changes to macros that might cause other edge-case issues, I'm OK with going ahead with this fix

@kyri-petrou kyri-petrou merged commit 1c90ddf into zio:series/2.x Nov 11, 2024
18 checks passed
@Saturn225 Saturn225 deleted the fix-error-msg branch November 11, 2024 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ZIO test throws when trying to print error messages (2.1.7->2.1.9)

2 participants