Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

NativeTextTests.cs 33KB

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