Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / RenderMultiColumnFlowThreadTest.cpp
1 // Copyright 2014 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 "config.h"
6
7 #include "core/rendering/RenderMultiColumnFlowThread.h"
8
9 #include "core/rendering/RenderMultiColumnSet.h"
10 #include "core/rendering/RenderMultiColumnSpannerSet.h"
11 #include "core/rendering/RenderingTestHelper.h"
12
13 #include <gtest/gtest.h>
14
15 namespace blink {
16
17 namespace {
18
19 class MultiColumnRenderingTest : public RenderingTest {
20 public:
21     RenderMultiColumnFlowThread* findFlowThread(const char* id) const;
22
23     // Generate a signature string based on what kind of column sets the flow thread has
24     // established. There will be one character for each column set. 'c' is used for regular column
25     // content sets, while 's' is used for spanner sets.
26     String columnSetSignature(RenderMultiColumnFlowThread*);
27     String columnSetSignature(const char* multicolId);
28
29     void setMulticolHTML(const String&);
30 };
31
32 RenderMultiColumnFlowThread* MultiColumnRenderingTest::findFlowThread(const char* id) const
33 {
34     Node* multicol = document().getElementById(id);
35     if (!multicol)
36         return 0;
37     RenderBlockFlow* multicolContainer = toRenderBlockFlow(multicol->renderer());
38     if (!multicolContainer)
39         return 0;
40     return multicolContainer->multiColumnFlowThread();
41 }
42
43 String MultiColumnRenderingTest::columnSetSignature(RenderMultiColumnFlowThread* flowThread)
44 {
45     String signature = "";
46     for (RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) {
47         if (columnSet->isRenderMultiColumnSpannerSet())
48             signature.append('s');
49         else
50             signature.append('c');
51     }
52     return signature;
53 }
54
55 String MultiColumnRenderingTest::columnSetSignature(const char* multicolId)
56 {
57     return columnSetSignature(findFlowThread(multicolId));
58 }
59
60 void MultiColumnRenderingTest::setMulticolHTML(const String& html)
61 {
62     const char* style =
63         "<style>"
64         "  #mc { -webkit-columns:2; }"
65         "  .s, #spanner, #spanner1, #spanner2 { -webkit-column-span:all; }"
66         "</style>";
67     setBodyInnerHTML(style + html);
68 }
69
70 TEST_F(MultiColumnRenderingTest, OneBlockWithInDepthTreeStructureCheck)
71 {
72     // Examine the render tree established by a simple multicol container with a block with some text inside.
73     setMulticolHTML("<div id='mc'><div>xxx</div></div>");
74     Node* multicol = document().getElementById("mc");
75     ASSERT_TRUE(multicol);
76     RenderBlockFlow* multicolContainer = toRenderBlockFlow(multicol->renderer());
77     ASSERT_TRUE(multicolContainer);
78     RenderMultiColumnFlowThread* flowThread = multicolContainer->multiColumnFlowThread();
79     ASSERT_TRUE(flowThread);
80     EXPECT_EQ(columnSetSignature(flowThread), "c");
81     EXPECT_EQ(flowThread->parent(), multicolContainer);
82     EXPECT_FALSE(flowThread->previousSibling());
83     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet();
84     ASSERT_TRUE(columnSet);
85     EXPECT_EQ(columnSet->previousSibling(), flowThread);
86     EXPECT_FALSE(columnSet->nextSibling());
87     RenderBlockFlow* block = toRenderBlockFlow(flowThread->firstChild());
88     ASSERT_TRUE(block);
89     EXPECT_FALSE(block->nextSibling());
90     ASSERT_TRUE(block->firstChild());
91     EXPECT_TRUE(block->firstChild()->isText());
92     EXPECT_FALSE(block->firstChild()->nextSibling());
93 }
94
95 TEST_F(MultiColumnRenderingTest, Empty)
96 {
97     // If there's no column content, there should be no column set.
98     setMulticolHTML("<div id='mc'></div>");
99     EXPECT_EQ(columnSetSignature("mc"), "");
100 }
101
102 TEST_F(MultiColumnRenderingTest, OneBlock)
103 {
104     // There is some content, so we should create a column set.
105     setMulticolHTML("<div id='mc'><div id='block'></div></div>");
106     ASSERT_EQ(columnSetSignature("mc"), "c");
107 }
108
109 TEST_F(MultiColumnRenderingTest, TwoBlocks)
110 {
111     // No matter how much content, we should only create one column set (unless there are spanners).
112     setMulticolHTML("<div id='mc'><div id='block1'></div><div id='block2'></div></div>");
113     ASSERT_EQ(columnSetSignature("mc"), "c");
114 }
115
116 TEST_F(MultiColumnRenderingTest, Spanner)
117 {
118     // With one spanner and no column content, we should create a spanner set.
119     setMulticolHTML("<div id='mc'><div id='spanner'></div></div>");
120     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
121     ASSERT_EQ(columnSetSignature(flowThread), "s");
122     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet();
123     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner")->renderer()), columnSet);
124 }
125
126 TEST_F(MultiColumnRenderingTest, ContentThenSpanner)
127 {
128     // With some column content followed by a spanner, we need a column set followed by a spanner set.
129     setMulticolHTML("<div id='mc'><div id='columnContent'></div><div id='spanner'></div></div>");
130     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
131     ASSERT_EQ(columnSetSignature(flowThread), "cs");
132     RenderMultiColumnSet* columnSet = flowThread->lastMultiColumnSet();
133     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner")->renderer()), columnSet);
134     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("columnContent")->renderer()), nullptr);
135 }
136
137 TEST_F(MultiColumnRenderingTest, SpannerThenContent)
138 {
139     // With a spanner followed by some column content, we need a spanner set followed by a column set.
140     setMulticolHTML("<div id='mc'><div id='spanner'></div><div id='columnContent'></div></div>");
141     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
142     ASSERT_EQ(columnSetSignature(flowThread), "sc");
143     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet();
144     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner")->renderer()), columnSet);
145     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("columnContent")->renderer()), nullptr);
146 }
147
148 TEST_F(MultiColumnRenderingTest, ContentThenSpannerThenContent)
149 {
150     // With column content followed by a spanner followed by some column content, we need a column
151     // set followed by a spanner set followed by a column set.
152     setMulticolHTML("<div id='mc'><div id='columnContentBefore'></div><div id='spanner'></div><div id='columnContentAfter'></div></div>");
153     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
154     ASSERT_EQ(columnSetSignature(flowThread), "csc");
155     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet()->nextSiblingMultiColumnSet();
156     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("columnContentBefore")->renderer()), nullptr);
157     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner")->renderer()), columnSet);
158     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("columnContentAfter")->renderer()), nullptr);
159 }
160
161 TEST_F(MultiColumnRenderingTest, TwoSpanners)
162 {
163     // With two spanners and no column content, we need two spanner sets.
164     setMulticolHTML("<div id='mc'><div id='spanner1'></div><div id='spanner2'></div></div>");
165     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
166     ASSERT_EQ(columnSetSignature(flowThread), "ss");
167     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet();
168     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner1")->renderer()), columnSet);
169     columnSet = columnSet->nextSiblingMultiColumnSet();
170     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner2")->renderer()), columnSet);
171 }
172
173 TEST_F(MultiColumnRenderingTest, SpannerThenContentThenSpanner)
174 {
175     // With two spanners and some column content in-between, we need a spanner set, a column set and another spanner set.
176     setMulticolHTML("<div id='mc'><div id='spanner1'></div><div id='columnContent'></div><div id='spanner2'></div></div>");
177     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
178     ASSERT_EQ(columnSetSignature(flowThread), "scs");
179     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet();
180     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner1")->renderer()), columnSet);
181     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("columnContent")->renderer()), nullptr);
182     columnSet = columnSet->nextSiblingMultiColumnSet()->nextSiblingMultiColumnSet();
183     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner2")->renderer()), columnSet);
184 }
185
186 TEST_F(MultiColumnRenderingTest, SpannerWithSpanner)
187 {
188     // column-span:all on something inside column-span:all has no effect.
189     setMulticolHTML("<div id='mc'><div id='spanner'><div id='invalidSpanner' class='s'></div></div></div>");
190     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
191     ASSERT_EQ(columnSetSignature(flowThread), "s");
192     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet();
193     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner")->renderer()), columnSet);
194     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("invalidSpanner")->renderer()), columnSet);
195     EXPECT_EQ(toRenderMultiColumnSpannerSet(columnSet)->rendererInFlowThread(), document().getElementById("spanner")->renderer());
196 }
197
198 TEST_F(MultiColumnRenderingTest, SubtreeWithSpanner)
199 {
200     setMulticolHTML("<div id='mc'><div id='outer'><div id='block1'></div><div id='spanner'></div><div id='block2'></div></div></div>");
201     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
202     EXPECT_EQ(columnSetSignature(flowThread), "csc");
203     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet()->nextSiblingMultiColumnSet();
204     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner")->renderer()), columnSet);
205     EXPECT_EQ(toRenderMultiColumnSpannerSet(columnSet)->rendererInFlowThread(), document().getElementById("spanner")->renderer());
206     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("outer")->renderer()), nullptr);
207     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("block1")->renderer()), nullptr);
208     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("block2")->renderer()), nullptr);
209 }
210
211 TEST_F(MultiColumnRenderingTest, SubtreeWithSpannerAfterSpanner)
212 {
213     setMulticolHTML("<div id='mc'><div id='spanner1'></div><div id='outer'>text<div id='spanner2'></div><div id='after'></div></div></div>");
214     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
215     EXPECT_EQ(columnSetSignature(flowThread), "scsc");
216     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet();
217     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner1")->renderer()), columnSet);
218     EXPECT_EQ(toRenderMultiColumnSpannerSet(columnSet)->rendererInFlowThread(), document().getElementById("spanner1")->renderer());
219     columnSet = columnSet->nextSiblingMultiColumnSet()->nextSiblingMultiColumnSet();
220     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner2")->renderer()), columnSet);
221     EXPECT_EQ(toRenderMultiColumnSpannerSet(columnSet)->rendererInFlowThread(), document().getElementById("spanner2")->renderer());
222     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("outer")->renderer()), nullptr);
223     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("after")->renderer()), nullptr);
224 }
225
226 TEST_F(MultiColumnRenderingTest, SubtreeWithSpannerBeforeSpanner)
227 {
228     setMulticolHTML("<div id='mc'><div id='outer'>text<div id='spanner1'></div>text</div><div id='spanner2'></div></div>");
229     RenderMultiColumnFlowThread* flowThread = findFlowThread("mc");
230     EXPECT_EQ(columnSetSignature(flowThread), "cscs");
231     RenderMultiColumnSet* columnSet = flowThread->firstMultiColumnSet()->nextSiblingMultiColumnSet();
232     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner1")->renderer()), columnSet);
233     EXPECT_EQ(toRenderMultiColumnSpannerSet(columnSet)->rendererInFlowThread(), document().getElementById("spanner1")->renderer());
234     columnSet = columnSet->nextSiblingMultiColumnSet()->nextSiblingMultiColumnSet();
235     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("spanner2")->renderer()), columnSet);
236     EXPECT_EQ(toRenderMultiColumnSpannerSet(columnSet)->rendererInFlowThread(), document().getElementById("spanner2")->renderer());
237     EXPECT_EQ(flowThread->containingColumnSpannerSet(document().getElementById("outer")->renderer()), nullptr);
238 }
239
240 } // anonymous namespace
241
242 } // namespace blink