OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "core/dom/custom/CustomElementReactionQueue.h" | |
6 | |
7 #include "core/dom/custom/CustomElementReaction.h" | |
8 #include "testing/gtest/include/gtest/gtest.h" | |
9 #include "wtf/text/AtomicString.h" | |
10 #include <initializer_list> | |
11 #include <vector> | |
12 | |
13 namespace blink { | |
14 | |
15 class Command : public GarbageCollectedFinalized<Command> { | |
16 WTF_MAKE_NONCOPYABLE(Command); | |
17 public: | |
18 Command() { } | |
19 virtual ~Command() { } | |
20 DEFINE_INLINE_VIRTUAL_TRACE() { } | |
21 virtual void run(Element*) = 0; | |
22 }; | |
23 | |
24 class Log : public Command { | |
25 WTF_MAKE_NONCOPYABLE(Log); | |
26 public: | |
27 Log(char what, std::vector<char>& where) : m_what(what), m_where(where) { } | |
28 virtual ~Log() { } | |
29 void run(Element*) override { m_where.push_back(m_what); } | |
30 private: | |
31 char m_what; | |
32 std::vector<char>& m_where; | |
33 }; | |
34 | |
35 class Recurse : public Command { | |
36 WTF_MAKE_NONCOPYABLE(Recurse); | |
37 public: | |
38 Recurse(CustomElementReactionQueue* queue) : m_queue(queue) { } | |
39 virtual ~Recurse() { } | |
40 DEFINE_INLINE_VIRTUAL_TRACE() | |
41 { | |
42 Command::trace(visitor); | |
43 visitor->trace(m_queue); | |
44 } | |
45 void run(Element* element) override { m_queue->invokeReactions(element); } | |
46 private: | |
47 Member<CustomElementReactionQueue> m_queue; | |
48 }; | |
49 | |
50 class Enqueue : public Command { | |
51 WTF_MAKE_NONCOPYABLE(Enqueue); | |
52 public: | |
53 Enqueue(CustomElementReactionQueue* queue, CustomElementReaction* reaction) | |
54 : m_queue(queue) | |
55 , m_reaction(reaction) | |
56 { | |
57 } | |
58 virtual ~Enqueue() { } | |
59 DEFINE_INLINE_VIRTUAL_TRACE() | |
60 { | |
61 Command::trace(visitor); | |
62 visitor->trace(m_queue); | |
63 visitor->trace(m_reaction); | |
64 } | |
65 void run(Element*) override | |
66 { | |
67 m_queue->add(m_reaction); | |
68 } | |
69 private: | |
70 Member<CustomElementReactionQueue> m_queue; | |
71 Member<CustomElementReaction> m_reaction; | |
72 }; | |
73 | |
74 class TestReaction : public CustomElementReaction { | |
75 WTF_MAKE_NONCOPYABLE(TestReaction); | |
76 public: | |
77 TestReaction(std::initializer_list<Command*> commands) | |
78 { | |
79 // TODO(dominicc): Simply pass the initializer list when | |
80 // HeapVector supports initializer lists like Vector. | |
81 for (auto& command : commands) | |
82 m_commands.append(command); | |
83 } | |
84 virtual ~TestReaction() = default; | |
85 DEFINE_INLINE_VIRTUAL_TRACE() | |
86 { | |
87 CustomElementReaction::trace(visitor); | |
88 visitor->trace(m_commands); | |
89 } | |
90 void invoke(Element* element) override | |
91 { | |
92 for (auto& command : m_commands) | |
93 command->run(element); | |
94 } | |
95 | |
96 private: | |
97 HeapVector<Member<Command>> m_commands; | |
98 }; | |
99 | |
100 TEST(CustomElementReactionQueueTest, invokeReactions_one) | |
101 { | |
102 std::vector<char> log; | |
103 CustomElementReactionQueue* queue = new CustomElementReactionQueue(); | |
104 queue->add(new TestReaction({new Log('a', log)})); | |
105 queue->invokeReactions(nullptr); | |
106 EXPECT_EQ(log, std::vector<char>({'a'})) | |
107 << "the reaction should have been invoked"; | |
108 } | |
109 | |
110 TEST(CustomElementReactionQueueTest, invokeReactions_many) | |
111 { | |
112 std::vector<char> log; | |
113 CustomElementReactionQueue* queue = new CustomElementReactionQueue(); | |
114 queue->add(new TestReaction({new Log('a', log)})); | |
115 queue->add(new TestReaction({new Log('b', log)})); | |
116 queue->add(new TestReaction({new Log('c', log)})); | |
117 queue->invokeReactions(nullptr); | |
118 EXPECT_EQ(log, std::vector<char>({'a', 'b', 'c'})) | |
119 << "the reaction should have been invoked"; | |
120 } | |
121 | |
122 TEST(CustomElementReactionQueueTest, invokeReactions_recursive) | |
123 { | |
124 std::vector<char> log; | |
125 CustomElementReactionQueue* queue = new CustomElementReactionQueue(); | |
126 | |
127 CustomElementReaction* third = new TestReaction({ | |
128 new Log('c', log), | |
129 new Recurse(queue)}); // "Empty" recursion | |
130 | |
131 CustomElementReaction* second = new TestReaction({ | |
132 new Log('b', log), | |
133 new Enqueue(queue, third)}); // Unwinds one level of recursion | |
134 | |
135 CustomElementReaction* first = new TestReaction({ | |
136 new Log('a', log), | |
137 new Enqueue(queue, second), | |
138 new Recurse(queue)}); // Non-empty recursion | |
139 | |
140 queue->add(first); | |
141 queue->invokeReactions(nullptr); | |
142 EXPECT_EQ(log, std::vector<char>({'a', 'b', 'c'})) | |
yosin_UTC9
2016/06/01 02:14:01
Wow, gtest's *_EQ(expect, actual) is now historica
| |
143 << "the reactions should have been invoked"; | |
144 } | |
145 | |
146 } // namespace blink | |
OLD | NEW |