1// Copyright 2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28var s = 'abcdefghijklmn';
29assertEquals(s, s.substr());
30assertEquals(s, s.substr(0));
31assertEquals(s, s.substr('0'));
32assertEquals(s, s.substr(void 0));
33assertEquals(s, s.substr(null));
34assertEquals(s, s.substr(false));
35assertEquals(s, s.substr(0.9));
36assertEquals(s, s.substr({ valueOf: function() { return 0; } }));
37assertEquals(s, s.substr({ toString: function() { return '0'; } }));
38
39var s1 = s.substring(1);
40assertEquals(s1, s.substr(1));
41assertEquals(s1, s.substr('1'));
42assertEquals(s1, s.substr(true));
43assertEquals(s1, s.substr(1.1));
44assertEquals(s1, s.substr({ valueOf: function() { return 1; } }));
45assertEquals(s1, s.substr({ toString: function() { return '1'; } }));
46
47
48assertEquals(s.substring(s.length - 1), s.substr(-1));
49assertEquals(s.substring(s.length - 1), s.substr(-1.2));
50assertEquals(s.substring(s.length - 1), s.substr(-1.7));
51assertEquals(s.substring(s.length - 2), s.substr(-2));
52assertEquals(s.substring(s.length - 2), s.substr(-2.3));
53assertEquals(s.substring(s.length - 2, s.length - 1), s.substr(-2, 1));
54assertEquals(s, s.substr(-100));
55assertEquals('abc', s.substr(-100, 3));
56assertEquals(s1, s.substr(-s.length + 1));
57
58// assertEquals('', s.substr(0, void 0)); // smjs and rhino
59assertEquals('abcdefghijklmn', s.substr(0, void 0));  // kjs and v8
60assertEquals('', s.substr(0, null));
61assertEquals(s, s.substr(0, String(s.length)));
62assertEquals('a', s.substr(0, true));
63
64
65// Test substrings of different lengths and alignments.
66// First ASCII.
67var x = "ASCII";
68for (var i = 0; i < 25; i++) {
69  x += (i >> 4).toString(16) + (i & 0x0f).toString(16);
70}
71/x/.exec(x);  // Try to force a flatten.
72for (var i = 5; i < 25; i++) {
73  for (var j = 0; j < 25; j++) {
74    var z = x.substring(i, i+j);
75    var w = Math.random() * 42;  // Allocate something new in new-space.
76    assertEquals(j, z.length);
77    for (var k = 0; k < j; k++) {
78      assertEquals(x.charAt(i+k), z.charAt(k));
79    }
80  }
81}
82
83
84// Then two-byte strings.
85x = "UC16\u2028";  // Non-ascii char forces two-byte string.
86for (var i = 0; i < 25; i++) {
87  x += (i >> 4).toString(16) + (i & 0x0f).toString(16);
88}
89/x/.exec(x);  // Try to force a flatten.
90for (var i = 5; i < 25; i++) {
91  for (var j = 0; j < 25; j++) {
92    var z = x.substring(i, i + j);
93    var w = Math.random() * 42;  // Allocate something new in new-space.
94    assertEquals(j, z.length);
95    for (var k = 0; k < j; k++) {
96      assertEquals(x.charAt(i+k), z.charAt(k));
97    }
98  }
99}
100
101
102// Keep creating strings to to force allocation failure on substring creation.
103var x = "0123456789ABCDEF";
104x += x;  // 2^5
105x += x;
106x += x;
107x += x;
108x += x;
109x += x;  // 2^10
110x += x;
111x += x;
112var xl = x.length;
113var cache = [];
114for (var i = 0; i < 10000; i++) {
115  var z = x.substring(i % xl);
116  assertEquals(xl - (i % xl), z.length);
117  cache.push(z);
118}
119
120
121// Same with two-byte strings
122var x = "\u2028123456789ABCDEF";
123x += x;  // 2^5
124x += x;
125x += x;
126x += x;
127x += x;
128x += x;  // 2^10
129x += x;
130x += x;
131var xl = x.length;
132var cache = [];
133for (var i = 0; i < 10000; i++) {
134  var z = x.substring(i % xl);
135  assertEquals(xl - (i % xl), z.length);
136  cache.push(z);
137}
138
139// Substring of substring.
140var cache = [];
141var last = x;
142var offset = 0;
143for (var i = 0; i < 64; i++) {
144  var z = last.substring(i);
145  last = z;
146  cache.push(z);
147  offset += i;
148}
149for (var i = 63; i >= 0; i--) {
150  var z = cache.pop();
151  assertTrue(/\u2028123456789ABCDEF/.test(z));
152  assertEquals(xl - offset, z.length);
153  offset -= i;
154}
155