reference_table_test.cc revision fa4333dcb481e564f54726b4e6f8153612df835e
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
1611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
1711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes#include "reference_table.h"
1811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
1946ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
2046ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
21a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe#include "class_linker.h"
22a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom#include "common_runtime_test.h"
23a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe#include "handle_scope-inl.h"
248db4c882a8d1996852163ebec966c8b4eb1e00dfAndreas Gampe#include "mirror/array-inl.h"
25e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "mirror/class-inl.h"
26a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe#include "mirror/class_loader.h"
27e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "mirror/string.h"
28e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "primitive.h"
29a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe#include "runtime.h"
300795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
31e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "thread-inl.h"
32a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom
3311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesnamespace art {
3411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
3546ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
3646ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
37a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstromclass ReferenceTableTest : public CommonRuntimeTest {};
3811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
39a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampestatic mirror::Object* CreateWeakReference(mirror::Object* referent)
40a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
41a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  Thread* self = Thread::Current();
42a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
43a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
44a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  StackHandleScope<3> scope(self);
45a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  Handle<mirror::Object> h_referent(scope.NewHandle<mirror::Object>(referent));
46a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
47a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  Handle<mirror::Class> h_ref_class(scope.NewHandle<mirror::Class>(
48a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe      class_linker->FindClass(self,
49a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe                              "Ljava/lang/ref/WeakReference;",
50a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe                              ScopedNullHandle<mirror::ClassLoader>())));
51fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  CHECK(h_ref_class != nullptr);
52a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  CHECK(class_linker->EnsureInitialized(self, h_ref_class, true, true));
53a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
54a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  Handle<mirror::Object> h_ref_instance(scope.NewHandle<mirror::Object>(
55a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe      h_ref_class->AllocObject(self)));
56fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  CHECK(h_ref_instance != nullptr);
57a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
58a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  ArtMethod* constructor = h_ref_class->FindDeclaredDirectMethod(
59a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe      "<init>", "(Ljava/lang/Object;)V", class_linker->GetImagePointerSize());
60a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  CHECK(constructor != nullptr);
61a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
62a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  uint32_t args[2];
63a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  args[0] = PointerToLowMemUInt32(h_ref_instance.Get());
64a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  args[1] = PointerToLowMemUInt32(h_referent.Get());
65a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  JValue result;
66a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  constructor->Invoke(self, args, sizeof(uint32_t), &result, constructor->GetShorty());
67a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  CHECK(!self->IsExceptionPending());
68a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
69a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  return h_ref_instance.Get();
70a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe}
71a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
7211e45077acba2e757799a00b3be9d63fec36a7ccElliott HughesTEST_F(ReferenceTableTest, Basics) {
7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* o1 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello");
7511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
7663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  ReferenceTable rt("test", 0, 11);
7763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
7863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  // Check dumping the empty table.
7963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  {
8063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    std::ostringstream oss;
8163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Dump(oss);
8263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_NE(oss.str().find("(empty)"), std::string::npos) << oss.str();
8363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(0U, rt.Size());
8463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  }
8563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
862cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Check removal of all nullss in a empty table is a no-op.
872cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  rt.Remove(nullptr);
8811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  EXPECT_EQ(0U, rt.Size());
8963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
9063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  // Check removal of all o1 in a empty table is a no-op.
9111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  rt.Remove(o1);
9211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  EXPECT_EQ(0U, rt.Size());
9363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
9463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  // Add o1 and check we have 1 element and can dump.
9563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  {
9663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Add(o1);
9763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(1U, rt.Size());
9863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    std::ostringstream oss;
9963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Dump(oss);
10063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_NE(oss.str().find("1 of java.lang.String"), std::string::npos) << oss.str();
10163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(oss.str().find("short[]"), std::string::npos) << oss.str();
10263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  }
10363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
10463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  // Add a second object 10 times and check dumping is sane.
1052dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* o2 = mirror::ShortArray::Alloc(soa.Self(), 0);
10663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  for (size_t i = 0; i < 10; ++i) {
10763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Add(o2);
10863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(i + 2, rt.Size());
10963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    std::ostringstream oss;
11063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Dump(oss);
11163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_NE(oss.str().find(StringPrintf("Last %zd entries (of %zd):",
11263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                                          i + 2 > 10 ? 10 : i + 2,
11363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                                          i + 2)),
11463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers              std::string::npos) << oss.str();
11563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_NE(oss.str().find("1 of java.lang.String"), std::string::npos) << oss.str();
11663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    if (i == 0) {
11763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers      EXPECT_NE(oss.str().find("1 of short[]"), std::string::npos) << oss.str();
11863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    } else {
11963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers      EXPECT_NE(oss.str().find(StringPrintf("%zd of short[] (1 unique instances)", i + 1)),
12063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                std::string::npos) << oss.str();
12163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    }
12263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  }
12363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
12463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  // Remove o1 (first element).
12563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  {
12663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Remove(o1);
12763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(10U, rt.Size());
12863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    std::ostringstream oss;
12963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Dump(oss);
13063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(oss.str().find("java.lang.String"), std::string::npos) << oss.str();
13163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  }
13263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
13363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  // Remove o2 ten times.
13463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  for (size_t i = 0; i < 10; ++i) {
13563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Remove(o2);
13663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(9 - i, rt.Size());
13763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    std::ostringstream oss;
13863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    rt.Dump(oss);
13963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    if (i == 9) {
14063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers      EXPECT_EQ(oss.str().find("short[]"), std::string::npos) << oss.str();
14163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    } else if (i == 8) {
14263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers      EXPECT_NE(oss.str().find("1 of short[]"), std::string::npos) << oss.str();
14363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    } else {
14463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers      EXPECT_NE(oss.str().find(StringPrintf("%zd of short[] (1 unique instances)", 10 - i - 1)),
14563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                std::string::npos) << oss.str();
14663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    }
14763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  }
148a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
149a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  // Add a reference and check that the type of the referent is dumped.
150a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  {
151a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    mirror::Object* empty_reference = CreateWeakReference(nullptr);
152a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    ASSERT_TRUE(empty_reference->IsReferenceInstance());
153a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    rt.Add(empty_reference);
154a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    std::ostringstream oss;
155a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    rt.Dump(oss);
156a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    EXPECT_NE(oss.str().find("java.lang.ref.WeakReference (referent is null)"), std::string::npos)
157a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe        << oss.str();
158a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  }
159a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe
160a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  {
161a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    mirror::Object* string_referent = mirror::String::AllocFromModifiedUtf8(Thread::Current(), "A");
162a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    mirror::Object* non_empty_reference = CreateWeakReference(string_referent);
163a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    ASSERT_TRUE(non_empty_reference->IsReferenceInstance());
164a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    rt.Add(non_empty_reference);
165a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    std::ostringstream oss;
166a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    rt.Dump(oss);
167a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe    EXPECT_NE(oss.str().find("java.lang.ref.WeakReference (referent is a java.lang.String)"),
168a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe              std::string::npos)
169a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe        << oss.str();
170a3bbf8bf436fd7567097b8ca0d7bd24fdf5ae08bAndreas Gampe  }
17111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
17211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
1736e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampestatic std::vector<size_t> FindAll(const std::string& haystack, const char* needle) {
1746e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::vector<size_t> res;
1756e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  size_t start = 0;
1766e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  do {
1776e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    size_t pos = haystack.find(needle, start);
1786e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    if (pos == std::string::npos) {
1796e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe      break;
1806e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    }
1816e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    res.push_back(pos);
1826e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    start = pos + 1;
1836e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  } while (start < haystack.size());
1846e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  return res;
1856e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe}
1866e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
1876e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas GampeTEST_F(ReferenceTableTest, SummaryOrder) {
1886e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  // Check that the summary statistics are sorted.
1896e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  ScopedObjectAccess soa(Thread::Current());
1906e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
1916e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  ReferenceTable rt("test", 0, 20);
1926e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
1936e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  {
1946e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    mirror::Object* s1 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello");
1956e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    mirror::Object* s2 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "world");
1966e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
1976e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    // 3 copies of s1, 2 copies of s2, interleaved.
1986e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    for (size_t i = 0; i != 2; ++i) {
1996e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe      rt.Add(s1);
2006e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe      rt.Add(s2);
2016e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    }
2026e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    rt.Add(s1);
2036e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  }
2046e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2056e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  {
2066e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    // Differently sized byte arrays. Should be sorted by identical (non-unique cound).
2076e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    mirror::Object* b1_1 = mirror::ByteArray::Alloc(soa.Self(), 1);
2086e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    rt.Add(b1_1);
2096e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
2106e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    rt.Add(b1_1);
2116e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
2126e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    rt.Add(mirror::ByteArray::Alloc(soa.Self(), 1));
2136e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe    rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
2146e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  }
2156e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2166e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  rt.Add(mirror::CharArray::Alloc(soa.Self(), 0));
2176e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2186e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  // Now dump, and ensure order.
2196e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::ostringstream oss;
2206e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  rt.Dump(oss);
2216e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2226e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  // Only do this on the part after Summary.
2236e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::string base = oss.str();
2246e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  size_t summary_pos = base.find("Summary:");
2256e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  ASSERT_NE(summary_pos, std::string::npos);
2266e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2276e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::string haystack = base.substr(summary_pos);
2286e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2296e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::vector<size_t> strCounts = FindAll(haystack, "java.lang.String");
2306e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::vector<size_t> b1Counts = FindAll(haystack, "byte[] (1 elements)");
2316e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::vector<size_t> b2Counts = FindAll(haystack, "byte[] (2 elements)");
2326e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  std::vector<size_t> cCounts = FindAll(haystack, "char[]");
2336e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2346e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  // Only one each.
2356e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  EXPECT_EQ(1u, strCounts.size());
2366e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  EXPECT_EQ(1u, b1Counts.size());
2376e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  EXPECT_EQ(1u, b2Counts.size());
2386e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  EXPECT_EQ(1u, cCounts.size());
2396e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
2406e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  // Expect them to be in order.
2416e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  EXPECT_LT(strCounts[0], b1Counts[0]);
2426e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  EXPECT_LT(b1Counts[0], b2Counts[0]);
2436e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe  EXPECT_LT(b2Counts[0], cCounts[0]);
2446e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe}
2456e970e7fa88efd5ee38b0d6f9010a3985c62778fAndreas Gampe
24611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}  // namespace art
247