Ei kuvausta
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NativeTextTests.cs 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. #if !NET_DOTS
  2. using System;
  3. using NUnit.Framework;
  4. using Unity.Collections;
  5. using Unity.Collections.LowLevel.Unsafe;
  6. using System.Text;
  7. using Unity.Burst;
  8. using Unity.Jobs;
  9. namespace FixedStringTests
  10. {
  11. internal class NativeTextTests
  12. {
  13. [Test]
  14. public void NativeTextFixedStringCtors()
  15. {
  16. using (NativeText aa = new NativeText(new FixedString32Bytes("test32"), Allocator.Temp))
  17. {
  18. Assert.True(aa != new FixedString32Bytes("test"));
  19. Assert.True(aa.Value == "test32");
  20. Assert.AreEqual("test32", aa);
  21. }
  22. using (NativeText aa = new NativeText(new FixedString64Bytes("test64"), Allocator.Temp))
  23. {
  24. Assert.True(aa != new FixedString64Bytes("test"));
  25. Assert.True(aa.Value == "test64");
  26. Assert.AreEqual("test64", aa);
  27. }
  28. using (NativeText aa = new NativeText(new FixedString128Bytes("test128"), Allocator.Temp))
  29. {
  30. Assert.True(aa != new FixedString128Bytes("test"));
  31. Assert.True(aa.Value == "test128");
  32. Assert.AreEqual("test128", aa);
  33. }
  34. using (NativeText aa = new NativeText(new FixedString512Bytes("test512"), Allocator.Temp))
  35. {
  36. Assert.True(aa != new FixedString512Bytes("test"));
  37. Assert.True(aa.Value == "test512");
  38. Assert.AreEqual("test512", aa);
  39. }
  40. using (NativeText aa = new NativeText(new FixedString4096Bytes("test4096"), Allocator.Temp))
  41. {
  42. Assert.True(aa != new FixedString4096Bytes("test"));
  43. Assert.True(aa.Value == "test4096");
  44. Assert.AreEqual("test4096", aa);
  45. }
  46. using (NativeText aa = new NativeText("testString", Allocator.Temp))
  47. {
  48. var s = "testString";
  49. Assert.AreEqual(aa, s);
  50. Assert.True(aa.Value == "testString");
  51. Assert.AreEqual("testString", aa);
  52. }
  53. }
  54. [Test]
  55. public void NativeTextCorrectLengthAfterClear()
  56. {
  57. NativeText aa = new NativeText(4, Allocator.Temp);
  58. Assert.True(aa.IsCreated);
  59. Assert.AreEqual(0, aa.Length, "Length after creation is not 0");
  60. aa.AssertNullTerminated();
  61. aa.Junk();
  62. aa.Clear();
  63. Assert.AreEqual(0, aa.Length, "Length after clear is not 0");
  64. aa.AssertNullTerminated();
  65. aa.Dispose();
  66. }
  67. [Test]
  68. public void NativeTextFormatExtension1Params()
  69. {
  70. NativeText aa = new NativeText(4, Allocator.Temp);
  71. Assert.True(aa.IsCreated);
  72. aa.Junk();
  73. FixedString32Bytes format = "{0}";
  74. FixedString32Bytes arg0 = "a";
  75. aa.AppendFormat(format, arg0);
  76. aa.Add(0x61);
  77. Assert.AreEqual("aa", aa);
  78. aa.AssertNullTerminated();
  79. aa.Dispose();
  80. }
  81. [Test]
  82. public void NativeTextFormatExtension2Params()
  83. {
  84. NativeText aa = new NativeText(4, Allocator.Temp);
  85. aa.Junk();
  86. FixedString32Bytes format = "{0} {1}";
  87. FixedString32Bytes arg0 = "a";
  88. FixedString32Bytes arg1 = "b";
  89. aa.AppendFormat(format, arg0, arg1);
  90. Assert.AreEqual("a b", aa);
  91. aa.AssertNullTerminated();
  92. aa.Dispose();
  93. }
  94. [Test]
  95. public void NativeTextFormatExtension3Params()
  96. {
  97. NativeText aa = new NativeText(4, Allocator.Temp);
  98. aa.Junk();
  99. FixedString32Bytes format = "{0} {1} {2}";
  100. FixedString32Bytes arg0 = "a";
  101. FixedString32Bytes arg1 = "b";
  102. FixedString32Bytes arg2 = "c";
  103. aa.AppendFormat(format, arg0, arg1, arg2);
  104. Assert.AreEqual("a b c", aa);
  105. aa.AssertNullTerminated();
  106. aa.Dispose();
  107. }
  108. [Test]
  109. public void NativeTextFormatExtension4Params()
  110. {
  111. NativeText aa = new NativeText(Allocator.Temp);
  112. aa.Junk();
  113. FixedString32Bytes format = "{0} {1} {2} {3}";
  114. FixedString32Bytes arg0 = "a";
  115. FixedString32Bytes arg1 = "b";
  116. FixedString32Bytes arg2 = "c";
  117. FixedString32Bytes arg3 = "d";
  118. aa.AppendFormat(format, arg0, arg1, arg2, arg3);
  119. Assert.AreEqual("a b c d", aa);
  120. aa.AssertNullTerminated();
  121. aa.Dispose();
  122. }
  123. [Test]
  124. public void NativeTextFormatExtension5Params()
  125. {
  126. NativeText aa = new NativeText(4, Allocator.Temp);
  127. aa.Junk();
  128. FixedString32Bytes format = "{0} {1} {2} {3} {4}";
  129. FixedString32Bytes arg0 = "a";
  130. FixedString32Bytes arg1 = "b";
  131. FixedString32Bytes arg2 = "c";
  132. FixedString32Bytes arg3 = "d";
  133. FixedString32Bytes arg4 = "e";
  134. aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4);
  135. Assert.AreEqual("a b c d e", aa);
  136. aa.AssertNullTerminated();
  137. aa.Dispose();
  138. }
  139. [Test]
  140. public void NativeTextFormatExtension6Params()
  141. {
  142. NativeText aa = new NativeText(4, Allocator.Temp);
  143. aa.Junk();
  144. FixedString32Bytes format = "{0} {1} {2} {3} {4} {5}";
  145. FixedString32Bytes arg0 = "a";
  146. FixedString32Bytes arg1 = "b";
  147. FixedString32Bytes arg2 = "c";
  148. FixedString32Bytes arg3 = "d";
  149. FixedString32Bytes arg4 = "e";
  150. FixedString32Bytes arg5 = "f";
  151. aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5);
  152. Assert.AreEqual("a b c d e f", aa);
  153. aa.AssertNullTerminated();
  154. aa.Dispose();
  155. }
  156. [Test]
  157. public void NativeTextFormatExtension7Params()
  158. {
  159. NativeText aa = new NativeText(4, Allocator.Temp);
  160. aa.Junk();
  161. FixedString32Bytes format = "{0} {1} {2} {3} {4} {5} {6}";
  162. FixedString32Bytes arg0 = "a";
  163. FixedString32Bytes arg1 = "b";
  164. FixedString32Bytes arg2 = "c";
  165. FixedString32Bytes arg3 = "d";
  166. FixedString32Bytes arg4 = "e";
  167. FixedString32Bytes arg5 = "f";
  168. FixedString32Bytes arg6 = "g";
  169. aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
  170. Assert.AreEqual("a b c d e f g", aa);
  171. aa.AssertNullTerminated();
  172. aa.Dispose();
  173. }
  174. [Test]
  175. public void NativeTextFormatExtension8Params()
  176. {
  177. NativeText aa = new NativeText(4, Allocator.Temp);
  178. aa.Junk();
  179. FixedString128Bytes format = "{0} {1} {2} {3} {4} {5} {6} {7}";
  180. FixedString32Bytes arg0 = "a";
  181. FixedString32Bytes arg1 = "b";
  182. FixedString32Bytes arg2 = "c";
  183. FixedString32Bytes arg3 = "d";
  184. FixedString32Bytes arg4 = "e";
  185. FixedString32Bytes arg5 = "f";
  186. FixedString32Bytes arg6 = "g";
  187. FixedString32Bytes arg7 = "h";
  188. aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  189. Assert.AreEqual("a b c d e f g h", aa);
  190. aa.AssertNullTerminated();
  191. aa.Dispose();
  192. }
  193. [Test]
  194. public void NativeTextFormatExtension9Params()
  195. {
  196. NativeText aa = new NativeText(4, Allocator.Temp);
  197. aa.Junk();
  198. FixedString128Bytes format = "{0} {1} {2} {3} {4} {5} {6} {7} {8}";
  199. FixedString32Bytes arg0 = "a";
  200. FixedString32Bytes arg1 = "b";
  201. FixedString32Bytes arg2 = "c";
  202. FixedString32Bytes arg3 = "d";
  203. FixedString32Bytes arg4 = "e";
  204. FixedString32Bytes arg5 = "f";
  205. FixedString32Bytes arg6 = "g";
  206. FixedString32Bytes arg7 = "h";
  207. FixedString32Bytes arg8 = "i";
  208. aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  209. Assert.AreEqual("a b c d e f g h i", aa);
  210. aa.AssertNullTerminated();
  211. aa.Dispose();
  212. }
  213. [Test]
  214. public void NativeTextFormatExtension10Params()
  215. {
  216. NativeText aa = new NativeText(4, Allocator.Temp);
  217. aa.Junk();
  218. FixedString128Bytes format = "{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}";
  219. FixedString32Bytes arg0 = "a";
  220. FixedString32Bytes arg1 = "b";
  221. FixedString32Bytes arg2 = "c";
  222. FixedString32Bytes arg3 = "d";
  223. FixedString32Bytes arg4 = "e";
  224. FixedString32Bytes arg5 = "f";
  225. FixedString32Bytes arg6 = "g";
  226. FixedString32Bytes arg7 = "h";
  227. FixedString32Bytes arg8 = "i";
  228. FixedString32Bytes arg9 = "j";
  229. aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
  230. Assert.AreEqual("a b c d e f g h i j", aa);
  231. aa.AssertNullTerminated();
  232. aa.Dispose();
  233. }
  234. [Test]
  235. public void NativeTextAppendGrows()
  236. {
  237. NativeText aa = new NativeText(1, Allocator.Temp);
  238. var origCapacity = aa.Capacity;
  239. for (int i = 0; i < origCapacity; ++i)
  240. aa.Append('a');
  241. Assert.AreEqual(origCapacity, aa.Capacity);
  242. aa.Append('b');
  243. Assert.GreaterOrEqual(aa.Capacity, origCapacity);
  244. Assert.AreEqual(new String('a', origCapacity) + "b", aa.ToString());
  245. aa.Dispose();
  246. }
  247. [Test]
  248. public void NativeTextAppendString()
  249. {
  250. NativeText aa = new NativeText(4, Allocator.Temp);
  251. aa.Append("aa");
  252. Assert.AreEqual("aa", aa.ToString());
  253. aa.Append("bb");
  254. Assert.AreEqual("aabb", aa.ToString());
  255. aa.Dispose();
  256. }
  257. [TestCase("Antidisestablishmentarianism")]
  258. [TestCase("⁣🌹🌻🌷🌿🌵🌾⁣")]
  259. public void NativeTextCopyFromBytesWorks(String a)
  260. {
  261. NativeText aa = new NativeText(4, Allocator.Temp);
  262. aa.Junk();
  263. var utf8 = Encoding.UTF8.GetBytes(a);
  264. unsafe
  265. {
  266. fixed (byte* b = utf8)
  267. aa.Append(b, (ushort) utf8.Length);
  268. }
  269. Assert.AreEqual(a, aa.ToString());
  270. aa.AssertNullTerminated();
  271. aa.Append("tail");
  272. Assert.AreEqual(a + "tail", aa.ToString());
  273. aa.AssertNullTerminated();
  274. aa.Dispose();
  275. }
  276. [TestCase("red")]
  277. [TestCase("紅色", TestName = "{m}(Chinese-Red)")]
  278. [TestCase("George Washington")]
  279. [TestCase("村上春樹", TestName = "{m}(HarukiMurakami)")]
  280. public void NativeTextToStringWorks(String a)
  281. {
  282. NativeText aa = new NativeText(4, Allocator.Temp);
  283. aa.Append(new FixedString128Bytes(a));
  284. Assert.AreEqual(a, aa.ToString());
  285. aa.AssertNullTerminated();
  286. aa.Dispose();
  287. }
  288. [TestCase("monkey", "monkey")]
  289. [TestCase("yellow", "green")]
  290. [TestCase("violet", "紅色", TestName = "{m}(Violet-Chinese-Red")]
  291. [TestCase("绿色", "蓝色", TestName = "{m}(Chinese-Green-Blue")]
  292. [TestCase("靛蓝色", "紫罗兰色", TestName = "{m}(Chinese-Indigo-Violet")]
  293. [TestCase("James Monroe", "John Quincy Adams")]
  294. [TestCase("Andrew Jackson", "村上春樹", TestName = "{m}(AndrewJackson-HarukiMurakami")]
  295. [TestCase("三島 由紀夫", "吉本ばなな", TestName = "{m}(MishimaYukio-YoshimotoBanana")]
  296. public void NativeTextEqualsWorks(String a, String b)
  297. {
  298. using (var aa = new NativeText(new FixedString128Bytes(a), Allocator.Temp))
  299. using (var bb = new NativeText(new FixedString128Bytes(b), Allocator.Temp))
  300. {
  301. Assert.AreEqual(aa.Equals(bb), a.Equals(b));
  302. aa.AssertNullTerminated();
  303. bb.AssertNullTerminated();
  304. }
  305. }
  306. [Test]
  307. public void NativeTextForEach()
  308. {
  309. NativeText actual = new NativeText("A🌕Z🌑D𒁃 𒁃𒁃𒁃𒁃𒁃", Allocator.Temp);
  310. FixedList128Bytes<uint> expected = default;
  311. expected.Add('A');
  312. expected.Add(0x1F315);
  313. expected.Add('Z');
  314. expected.Add(0x1F311);
  315. expected.Add('D');
  316. expected.Add(0x12043);
  317. expected.Add(' ');
  318. expected.Add(0x12043);
  319. expected.Add(0x12043);
  320. expected.Add(0x12043);
  321. expected.Add(0x12043);
  322. expected.Add(0x12043);
  323. int index = 0;
  324. foreach (var rune in actual)
  325. {
  326. Assert.AreEqual(expected[index], rune.value);
  327. ++index;
  328. }
  329. actual.Dispose();
  330. }
  331. [Test]
  332. public void NativeTextIndexOf()
  333. {
  334. NativeText a = new NativeText("bookkeeper bookkeeper", Allocator.Temp);
  335. NativeText b = new NativeText("ookkee", Allocator.Temp);
  336. Assert.AreEqual(1, a.IndexOf(b));
  337. Assert.AreEqual(-1, b.IndexOf(a));
  338. a.Dispose();
  339. b.Dispose();
  340. }
  341. [Test]
  342. public void NativeTextLastIndexOf()
  343. {
  344. NativeText a = new NativeText("bookkeeper bookkeeper", Allocator.Temp);
  345. NativeText b = new NativeText("ookkee", Allocator.Temp);
  346. Assert.AreEqual(12, a.LastIndexOf(b));
  347. Assert.AreEqual(-1, b.LastIndexOf(a));
  348. a.Dispose();
  349. b.Dispose();
  350. }
  351. [Test]
  352. public void NativeTextContains()
  353. {
  354. NativeText a = new NativeText("bookkeeper", Allocator.Temp);
  355. NativeText b = new NativeText("ookkee", Allocator.Temp);
  356. Assert.AreEqual(true, a.Contains(b));
  357. a.Dispose();
  358. b.Dispose();
  359. }
  360. [Test]
  361. public void NativeTextComparisons()
  362. {
  363. using (var a = new NativeText("apple", Allocator.Temp))
  364. using (var b = new NativeText("banana", Allocator.Temp))
  365. {
  366. Assert.AreEqual(false, a.Equals(b));
  367. Assert.AreEqual(true, !b.Equals(a));
  368. }
  369. }
  370. [Test]
  371. public void NativeText_CustomAllocatorTest()
  372. {
  373. AllocatorManager.Initialize();
  374. var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
  375. ref var allocator = ref allocatorHelper.Allocator;
  376. allocator.Initialize();
  377. using (var container = new NativeText(allocator.Handle))
  378. {
  379. }
  380. Assert.IsTrue(allocator.WasUsed);
  381. allocator.Dispose();
  382. allocatorHelper.Dispose();
  383. AllocatorManager.Shutdown();
  384. }
  385. [BurstCompile]
  386. struct BurstedCustomAllocatorJob : IJob
  387. {
  388. [NativeDisableUnsafePtrRestriction]
  389. public unsafe CustomAllocatorTests.CountingAllocator* Allocator;
  390. public void Execute()
  391. {
  392. unsafe
  393. {
  394. using (var container = new NativeText(Allocator->Handle))
  395. {
  396. }
  397. }
  398. }
  399. }
  400. [Test]
  401. public unsafe void NativeText_BurstedCustomAllocatorTest()
  402. {
  403. AllocatorManager.Initialize();
  404. var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
  405. ref var allocator = ref allocatorHelper.Allocator;
  406. allocator.Initialize();
  407. var allocatorPtr = (CustomAllocatorTests.CountingAllocator*)UnsafeUtility.AddressOf<CustomAllocatorTests.CountingAllocator>(ref allocator);
  408. unsafe
  409. {
  410. var handle = new BurstedCustomAllocatorJob {Allocator = allocatorPtr}.Schedule();
  411. handle.Complete();
  412. }
  413. Assert.IsTrue(allocator.WasUsed);
  414. allocator.Dispose();
  415. allocatorHelper.Dispose();
  416. AllocatorManager.Shutdown();
  417. }
  418. [Test]
  419. public void NativeTextIsEmpty()
  420. {
  421. var a = new NativeText("", Allocator.Temp);
  422. Assert.IsTrue(a.IsEmpty);
  423. a.CopyFrom("hello");
  424. Assert.IsFalse(a.IsEmpty);
  425. a.Dispose();
  426. }
  427. [Test]
  428. public void NativeTextIsEmptyReturnsTrueForNotConstructed()
  429. {
  430. NativeText a = default;
  431. Assert.IsTrue(a.IsEmpty);
  432. }
  433. [Test]
  434. public void NativeTextReadonlyCtor()
  435. {
  436. using (NativeText aa = new NativeText(new FixedString32Bytes("test32"), Allocator.Temp))
  437. {
  438. var ro = aa.AsReadOnly();
  439. Assert.True(ro != new FixedString32Bytes("test"));
  440. Assert.True(ro.Value == "test32");
  441. Assert.AreEqual("test32", ro);
  442. }
  443. using (NativeText aa = new NativeText(new FixedString64Bytes("test64"), Allocator.Temp))
  444. {
  445. var ro = aa.AsReadOnly();
  446. Assert.True(ro != new FixedString64Bytes("test"));
  447. Assert.True(ro.Value == "test64");
  448. Assert.AreEqual("test64", ro);
  449. }
  450. using (NativeText aa = new NativeText(new FixedString128Bytes("test128"), Allocator.Temp))
  451. {
  452. var ro = aa.AsReadOnly();
  453. Assert.True(ro != new FixedString128Bytes("test"));
  454. Assert.True(ro.Value == "test128");
  455. Assert.AreEqual("test128", ro);
  456. }
  457. using (NativeText aa = new NativeText(new FixedString512Bytes("test512"), Allocator.Temp))
  458. {
  459. var ro = aa.AsReadOnly();
  460. Assert.True(ro != new FixedString512Bytes("test"));
  461. Assert.True(ro.Value == "test512");
  462. Assert.AreEqual("test512", ro);
  463. }
  464. using (NativeText aa = new NativeText(new FixedString4096Bytes("test4096"), Allocator.Temp))
  465. {
  466. var ro = aa.AsReadOnly();
  467. Assert.True(ro != new FixedString4096Bytes("test"));
  468. Assert.True(ro.Value == "test4096");
  469. Assert.AreEqual("test4096", ro);
  470. }
  471. using (var aa = new NativeText("Hello", Allocator.Temp))
  472. {
  473. var ro = aa.AsReadOnly();
  474. Assert.AreEqual(aa.Equals(ro), ro.Equals(aa));
  475. aa.AssertNullTerminated();
  476. ro.AssertNullTerminated();
  477. }
  478. }
  479. [TestCase("monkey", "monkey")]
  480. [TestCase("yellow", "green")]
  481. [TestCase("violet", "紅色", TestName = "{m}(Violet-Chinese-Red")]
  482. [TestCase("绿色", "蓝色", TestName = "{m}(Chinese-Green-Blue")]
  483. [TestCase("靛蓝色", "紫罗兰色", TestName = "{m}(Chinese-Indigo-Violet")]
  484. [TestCase("James Monroe", "John Quincy Adams")]
  485. [TestCase("Andrew Jackson", "村上春樹", TestName = "{m}(AndrewJackson-HarukiMurakami")]
  486. [TestCase("三島 由紀夫", "吉本ばなな", TestName = "{m}(MishimaYukio-YoshimotoBanana")]
  487. public void NativeTextReadOnlyEqualsWorks(String a, String b)
  488. {
  489. using (var aa = new NativeText(new FixedString128Bytes(a), Allocator.Temp))
  490. using (var bb = new NativeText(new FixedString128Bytes(b), Allocator.Temp))
  491. {
  492. var aaRO = aa.AsReadOnly();
  493. var bbRO = bb.AsReadOnly();
  494. Assert.AreEqual(aaRO.Equals(bbRO), a.Equals(b));
  495. aaRO.AssertNullTerminated();
  496. bbRO.AssertNullTerminated();
  497. }
  498. }
  499. [Test]
  500. public void NativeTextReadOnlyIndexOf()
  501. {
  502. using (var a = new NativeText("bookkeeper bookkeeper", Allocator.Temp))
  503. using (var b = new NativeText("ookkee", Allocator.Temp))
  504. {
  505. var aRO = a.AsReadOnly();
  506. var bRO = b.AsReadOnly();
  507. Assert.AreEqual(1, aRO.IndexOf(bRO));
  508. Assert.AreEqual(-1, bRO.IndexOf(aRO));
  509. }
  510. }
  511. [Test]
  512. public void NativeTextReadOnlyLastIndexOf()
  513. {
  514. using (var a = new NativeText("bookkeeper bookkeeper", Allocator.Temp))
  515. using (var b = new NativeText("ookkee", Allocator.Temp))
  516. {
  517. var aRO = a.AsReadOnly();
  518. var bRO = b.AsReadOnly();
  519. Assert.AreEqual(12, aRO.LastIndexOf(bRO));
  520. Assert.AreEqual(-1, bRO.LastIndexOf(aRO));
  521. }
  522. }
  523. [Test]
  524. public void NativeTextReadOnlyContains()
  525. {
  526. using (var a = new NativeText("bookkeeper", Allocator.Temp))
  527. using (var b = new NativeText("ookkee", Allocator.Temp))
  528. {
  529. var aRO = a.AsReadOnly();
  530. var bRO = b.AsReadOnly();
  531. Assert.AreEqual(true, aRO.Contains(bRO));
  532. }
  533. }
  534. [Test]
  535. public void NativeTextReadOnlyComparisons()
  536. {
  537. using (var a = new NativeText("apple", Allocator.Temp))
  538. using (var b = new NativeText("banana", Allocator.Temp))
  539. {
  540. var aRO = a.AsReadOnly();
  541. var bRO = b.AsReadOnly();
  542. Assert.AreEqual(false, aRO.Equals(bRO));
  543. Assert.AreEqual(true, !bRO.Equals(aRO));
  544. }
  545. }
  546. [Test]
  547. public void NativeTextReadOnlyMakeMoreThanOne()
  548. {
  549. using (var a = new NativeText("apple", Allocator.Temp))
  550. {
  551. var aRO1 = a.AsReadOnly();
  552. var aRO2 = a.AsReadOnly();
  553. Assert.IsTrue(a.Equals(aRO1));
  554. Assert.IsTrue(aRO1.Equals(aRO2));
  555. Assert.IsTrue(aRO2.Equals(aRO1));
  556. }
  557. }
  558. [Test]
  559. public void NativeTextReadOnlyIsNotACopy()
  560. {
  561. using (var a = new NativeText("apple", Allocator.Temp))
  562. {
  563. var aRO = a.AsReadOnly();
  564. Assert.AreEqual(true, aRO.Equals(a));
  565. unsafe
  566. {
  567. Assert.IsTrue(aRO.GetUnsafePtr() == a.GetUnsafePtr());
  568. }
  569. }
  570. }
  571. [Test]
  572. public void NativeTextReadOnlyIsEmpty()
  573. {
  574. var a = new NativeText("", Allocator.Temp);
  575. var aRO = a.AsReadOnly();
  576. Assert.IsTrue(aRO.IsEmpty);
  577. a.Dispose();
  578. a = new NativeText("not empty", Allocator.Temp);
  579. aRO = a.AsReadOnly();
  580. Assert.IsFalse(aRO.IsEmpty);
  581. a.Dispose();
  582. }
  583. [Test]
  584. public void NativeTextReadOnlyIsEmptyReturnsTrueOrThrowsForNotConstructed()
  585. {
  586. NativeText.ReadOnly aRO = default;
  587. Assert.IsTrue(aRO.IsEmpty);
  588. #if ENABLE_UNITY_COLLECTIONS_CHECKS
  589. NativeText aa = default;
  590. NativeText.ReadOnly aaRO = aa.AsReadOnly();
  591. Assert.IsTrue(aaRO.IsEmpty);
  592. #endif
  593. }
  594. [Test]
  595. public void NativeTextReadOnlyIsNotWritable()
  596. {
  597. using (var a = new NativeText("apple", Allocator.Temp))
  598. {
  599. var aRO = a.AsReadOnly();
  600. Assert.AreEqual(true, aRO.Equals(a));
  601. Assert.Throws<NotSupportedException>(() => { aRO.IsEmpty = true; });
  602. Assert.Throws<NotSupportedException>(() => { aRO.Length = 0; });
  603. Assert.Throws<NotSupportedException>(() => { aRO.Capacity = 0; });
  604. Assert.Throws<NotSupportedException>(() => { aRO.ElementAt(0); });
  605. Assert.Throws<NotSupportedException>(() => { aRO.Clear(); });
  606. Assert.Throws<NotSupportedException>(() => { aRO.Append("won't work"); });
  607. FixedString32Bytes format = "{0}";
  608. FixedString32Bytes arg0 = "a";
  609. Assert.Throws<NotSupportedException>(() => { aRO.AppendFormat(format, arg0); });
  610. Assert.Throws<NotSupportedException>(() => { aRO.AppendRawByte(1); });
  611. Assert.Throws<NotSupportedException>(() => { aRO.TryResize(0); });
  612. }
  613. }
  614. [Test]
  615. public void NativeTextReadOnlyCannotBeUsedAfterSourceIsDisposed()
  616. {
  617. AllocatorManager.Initialize();
  618. using (var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent))
  619. {
  620. ref var allocator = ref allocatorHelper.Allocator;
  621. allocator.Initialize();
  622. var a = new NativeText("Keep it secret, ", allocator.Handle);
  623. var ro = a.AsReadOnly();
  624. a.Dispose(); // Invalidate the string we are referring to
  625. Assert.Throws<ObjectDisposedException>(() => { UnityEngine.Debug.Log(ro.ToString()); });
  626. Assert.IsTrue(allocator.WasUsed);
  627. allocator.Dispose();
  628. }
  629. AllocatorManager.Shutdown();
  630. }
  631. [Test]
  632. public void NativeTextReadOnlyCannotBeUsedAfterSourceIsChanged()
  633. {
  634. AllocatorManager.Initialize();
  635. using (var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent))
  636. {
  637. ref var allocator = ref allocatorHelper.Allocator;
  638. allocator.Initialize();
  639. var a = new NativeText("Keep it secret, ", allocator.Handle);
  640. var ro = a.AsReadOnly();
  641. a.Clear(); // Change the string we are referring to
  642. Assert.DoesNotThrow(() => { UnityEngine.Debug.Log(ro.ToString()); });
  643. a.Dispose();
  644. Assert.Throws<ObjectDisposedException>(() => { UnityEngine.Debug.Log(ro.ToString()); });
  645. Assert.IsTrue(allocator.WasUsed);
  646. allocator.Dispose();
  647. }
  648. AllocatorManager.Shutdown();
  649. }
  650. [Test]
  651. public void NativeTextReadOnlyModificationDuringEnumerationThrows()
  652. {
  653. AllocatorManager.Initialize();
  654. using (var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent))
  655. {
  656. ref var allocator = ref allocatorHelper.Allocator;
  657. allocator.Initialize();
  658. var a = new NativeText("Keep it secret, ", allocator.Handle);
  659. var ro = a.AsReadOnly();
  660. int iterations = 0;
  661. Assert.Throws<ObjectDisposedException>(() =>
  662. {
  663. // Mutate the source string while iterating. Can append once but when we use the iterator
  664. // again it will now be invalid and should throw
  665. foreach (var c in ro)
  666. {
  667. iterations++;
  668. a.Append("keep it safe, ");
  669. }
  670. });
  671. Assert.AreEqual(1, iterations);
  672. a.Dispose();
  673. Assert.IsTrue(allocator.WasUsed);
  674. allocator.Dispose();
  675. }
  676. AllocatorManager.Shutdown();
  677. }
  678. struct TestWriteOfTextMappedToReadOnly : IJob
  679. {
  680. public NativeText Text;
  681. public void Execute() { }
  682. }
  683. struct TestClearTextMappedToReadOnly : IJob
  684. {
  685. public NativeText Text;
  686. public void Execute()
  687. {
  688. Text.Clear();
  689. }
  690. }
  691. [Test]
  692. public void NativeTextReadOnlyCannotScheduledSourceTextForWrite()
  693. {
  694. AllocatorManager.Initialize();
  695. using (var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent))
  696. {
  697. ref var allocator = ref allocatorHelper.Allocator;
  698. allocator.Initialize();
  699. var a = new NativeText("Keep it secret, ", allocator.Handle);
  700. var ro = a.AsReadOnly();
  701. var job = new TestWriteOfTextMappedToReadOnly
  702. {
  703. Text = a
  704. };
  705. var handle = job.Schedule();
  706. Assert.Throws<InvalidOperationException>(() =>
  707. {
  708. UnityEngine.Debug.Log(ro.ToString());
  709. });
  710. Assert.Throws<InvalidOperationException>(() =>
  711. {
  712. a.Dispose();
  713. });
  714. handle.Complete();
  715. Assert.IsTrue(allocator.WasUsed);
  716. allocator.Dispose();
  717. }
  718. AllocatorManager.Shutdown();
  719. }
  720. [Test]
  721. public void NativeTextReadOnlyCanReadFromSourceTextModifiedInJob()
  722. {
  723. AllocatorManager.Initialize();
  724. using (var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent))
  725. {
  726. ref var allocator = ref allocatorHelper.Allocator;
  727. allocator.Initialize();
  728. var a = new NativeText("Keep it secret, ", allocator.Handle);
  729. var ro = a.AsReadOnly();
  730. var job = new TestClearTextMappedToReadOnly
  731. {
  732. Text = a
  733. };
  734. var handle = job.Schedule();
  735. handle.Complete();
  736. Assert.DoesNotThrow(() =>
  737. {
  738. UnityEngine.Debug.Log(ro.ToString());
  739. });
  740. Assert.IsTrue(allocator.WasUsed);
  741. allocator.Dispose();
  742. }
  743. AllocatorManager.Shutdown();
  744. }
  745. struct TestReadOfTextMappedToReadOnly : IJob
  746. {
  747. [ReadOnly]
  748. public NativeText Text;
  749. public void Execute() { }
  750. }
  751. [Test]
  752. public void NativeTextReadOnlyCanScheduledSourceTextForRead()
  753. {
  754. AllocatorManager.Initialize();
  755. using (var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent))
  756. {
  757. ref var allocator = ref allocatorHelper.Allocator;
  758. allocator.Initialize();
  759. var a = new NativeText("Keep it secret, ", allocator.Handle);
  760. var ro = a.AsReadOnly();
  761. var job = new TestReadOfTextMappedToReadOnly
  762. {
  763. Text = a
  764. };
  765. Assert.DoesNotThrow(() =>
  766. {
  767. job.Schedule().Complete();
  768. });
  769. a.Dispose();
  770. Assert.IsTrue(allocator.WasUsed);
  771. allocator.Dispose();
  772. }
  773. AllocatorManager.Shutdown();
  774. }
  775. struct TestReadFromReadOnly : IJob
  776. {
  777. [ReadOnly] public NativeText.ReadOnly RO;
  778. public void Execute()
  779. {
  780. UnityEngine.Debug.Log($"{RO.Length}");
  781. }
  782. }
  783. [Test]
  784. public void NativeTextReadOnlyThrowWhenUsingReadOnlyInJobAfterSourceHasBeenDisposed()
  785. {
  786. AllocatorManager.Initialize();
  787. using (var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent))
  788. {
  789. ref var allocator = ref allocatorHelper.Allocator;
  790. allocator.Initialize();
  791. var a = new NativeText("Keep it secret, ", allocator.Handle);
  792. var job = new TestReadFromReadOnly
  793. {
  794. RO = a.AsReadOnly()
  795. };
  796. var handle = job.Schedule();
  797. Assert.Throws<InvalidOperationException>(() =>
  798. {
  799. a.Dispose();
  800. });
  801. Assert.IsTrue(allocator.WasUsed);
  802. allocator.Dispose();
  803. }
  804. AllocatorManager.Shutdown();
  805. }
  806. }
  807. }
  808. #endif