| Index: ios/chrome/common/block_unittest.mm
|
| diff --git a/ios/chrome/common/block_unittest.mm b/ios/chrome/common/block_unittest.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3ff46f844670e17057d67ea6eefa6be6e3c4a0d6
|
| --- /dev/null
|
| +++ b/ios/chrome/common/block_unittest.mm
|
| @@ -0,0 +1,100 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#import <Foundation/Foundation.h>
|
| +#include <vector>
|
| +
|
| +#include "base/memory/ref_counted.h"
|
| +#include "testing/platform_test.h"
|
| +
|
| +// This test verifies assumptions about the murky world of interaction between
|
| +// C++ objects and blocks. Just to make sure.
|
| +
|
| +namespace {
|
| +
|
| +class RefCountedObject : public base::RefCounted<RefCountedObject> {
|
| + public:
|
| + RefCountedObject() {}
|
| +
|
| + // Refcount is private in the superclass, fake it by counting how many times
|
| + // release can be called until there is one count left, then retain the count
|
| + // back.
|
| + int refcount() {
|
| + int count = 1;
|
| + while (!HasOneRef()) {
|
| + bool check = base::subtle::RefCountedBase::Release();
|
| + EXPECT_FALSE(check);
|
| + ++count;
|
| + }
|
| + for (int ii = 1; ii < count; ii++)
|
| + base::subtle::RefCountedBase::AddRef();
|
| + return count;
|
| + }
|
| +
|
| + protected:
|
| + friend base::RefCounted<RefCountedObject>;
|
| + virtual ~RefCountedObject() {}
|
| +};
|
| +
|
| +TEST_F(PlatformTest, BlockAndCPlusPlus) {
|
| + RefCountedObject* object = new RefCountedObject();
|
| + object->AddRef();
|
| + EXPECT_TRUE(object->HasOneRef());
|
| + EXPECT_EQ(1, object->refcount());
|
| +
|
| + {
|
| + scoped_refptr<RefCountedObject> object_test_ptr(object);
|
| + EXPECT_EQ(2, object->refcount());
|
| + }
|
| + EXPECT_TRUE(object->HasOneRef());
|
| +
|
| + void (^heap_block)(int) = 0;
|
| + {
|
| + scoped_refptr<RefCountedObject> object_ptr(object);
|
| + EXPECT_EQ(2, object->refcount());
|
| + void* object_void_ptr = (void*)object;
|
| +
|
| + void (^stack_block)(int) = ^(int expected) {
|
| + EXPECT_EQ(object_void_ptr, object_ptr.get());
|
| + EXPECT_EQ(expected, object_ptr.get()->refcount());
|
| + };
|
| + stack_block(3);
|
| + heap_block = [stack_block copy];
|
| + stack_block(4);
|
| + }
|
| + heap_block(2);
|
| + [heap_block release];
|
| + EXPECT_TRUE(object->HasOneRef());
|
| + {
|
| + scoped_refptr<RefCountedObject> object_test2_ptr(object);
|
| + EXPECT_EQ(2, object->refcount());
|
| + }
|
| + EXPECT_TRUE(object->HasOneRef());
|
| + object->Release();
|
| +}
|
| +
|
| +TEST_F(PlatformTest, BlockAndVectors) {
|
| + void (^heap_block)(void) = 0;
|
| + {
|
| + std::vector<int> vector;
|
| + vector.push_back(0);
|
| + vector.push_back(1);
|
| + vector.push_back(2);
|
| +
|
| + void (^stack_block)(void) = ^{
|
| + EXPECT_EQ(3ul, vector.size());
|
| + EXPECT_EQ(2, vector[2]);
|
| + };
|
| + stack_block();
|
| + vector[2] = 42;
|
| + vector.push_back(22);
|
| + stack_block();
|
| + heap_block = [stack_block copy];
|
| + stack_block();
|
| + }
|
| + heap_block();
|
| + [heap_block release];
|
| +}
|
| +
|
| +} // namespace
|
|
|