summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/translate/page_translator_unittest.cc
blob: 02f1b32c6fce81bfdf05409a7ecdce8e82e4cf40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// Copyright (c) 2010 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.

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "chrome/renderer/translate/page_translator.h"
#include "chrome/test/render_view_test.h"
#include "net/base/net_errors.h"

class TranslatorTest : public RenderViewTest {
 public:
  TranslatorTest() {}
};

// A TextTranslator used that simply reverse the strings that are provided to
// it.
class ReverseTextTranslator : public TextTranslator {
 public:
  ReverseTextTranslator()
      : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
        work_id_counter_(0) {
  }

  virtual int Translate(const std::vector<string16>& text_chunks,
                        std::string from_lang,
                        std::string to_lang,
                        bool secure,
                        TextTranslator::Delegate* delegate) {
    int work_id = work_id_counter_++;

    std::vector<string16> translated_text_chunks;
    for (std::vector<string16>::const_iterator iter = text_chunks.begin();
         iter != text_chunks.end(); ++iter) {
      translated_text_chunks.push_back(ReverseString(*iter));
    }
    MessageLoop::current()->PostTask(FROM_HERE,
        method_factory_.NewRunnableMethod(
            &ReverseTextTranslator::NotifyDelegate,
            work_id,
            translated_text_chunks,
            delegate));
    return work_id;
  }

 private:
  void NotifyDelegate(int work_id,
                      const std::vector<string16>& text_chunks,
                      TextTranslator::Delegate* delegate) {
    delegate->TextTranslated(work_id, text_chunks);
  }

  string16 ReverseString(const string16& str) {
    string16 result;
    for (string16::const_reverse_iterator iter = str.rbegin();
         iter != str.rend(); ++iter) {
      result.push_back(*iter);
    }
    return result;
  }

  ScopedRunnableMethodFactory<ReverseTextTranslator> method_factory_;

  int work_id_counter_;

  DISALLOW_COPY_AND_ASSIGN(ReverseTextTranslator);
};

// A simple ResourceLoaderBridge that always fails to load.
class DummyResourceLoaderBridge : public webkit_glue::ResourceLoaderBridge {
 public:
  DummyResourceLoaderBridge() { }

  virtual void AppendDataToUpload(const char* data, int data_len) {}
  virtual void AppendFileRangeToUpload(
      const FilePath& file_path,
      uint64 offset,
      uint64 length,
      const base::Time& expected_modification_time) {}
  virtual void SetUploadIdentifier(int64 identifier) {}
  virtual bool Start(Peer* peer) { return false; }
  virtual void Cancel() {}
  virtual void SetDefersLoading(bool value) {}
  virtual void SyncLoad(SyncLoadResponse* response) {
    response->status.set_status(URLRequestStatus::FAILED);
    response->status.set_os_error(net::ERR_FAILED);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DummyResourceLoaderBridge);
};

// A ChildThread class that creates a dummy resource loader bridge so that
// page with resources can be loaded (as data:...) without asserting.
class TestChildThread : public ChildThread {
 public:
  TestChildThread() {}

  virtual webkit_glue::ResourceLoaderBridge* CreateBridge(
      const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info,
      int host_renderer_id,
      int host_render_view_id) {
    return new DummyResourceLoaderBridge;
  }

  // Overriden so it does not terminate the message loop. That would assert as
  // the message loop is running in the test.
  virtual void OnProcessFinalRelease() { }
};

// Tests that we parse and change text in pages correctly.
// It loads all the <name>_ORIGINAL.html files under the
// chrome/test/data/translate directory.  There must be a matching
// <name>_TRANLSATED.html in the directory.
// The _ORIGINAL page is loaded and translated.
// The result is compared to the _TRANSLATED page.
// Note: _TRANSLATED.html files can be generated using the reverse_text.py
// script located in the chrome/test/data/translate directory.
// TODO(jcampan): http://crbug.com/32217 This test is disabled as it sometimes
//                fails on Windows and always fails on Unix.  We need to improve
//                RenderViewTest so it supports loading tags that contain links
//                and sub-resources.
TEST_F(TranslatorTest, DISABLED_TranslatePages) {
  // Create the RenderThread singleton. Rendering pages requires a
  // VisitedLinkSlave that this object creates.
  RenderThread render_thread;

  // Create the ChildThread singleton. It is used to create the resource
  // bridges. (It is owned by the ChildProcess.)
  ChildProcess::current()->set_main_thread(new TestChildThread());

  FilePath data_dir;
  ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
  data_dir = data_dir.Append(FILE_PATH_LITERAL("chrome"));
  data_dir = data_dir.Append(FILE_PATH_LITERAL("test"));
  data_dir = data_dir.Append(FILE_PATH_LITERAL("data"));
  data_dir = data_dir.Append(FILE_PATH_LITERAL("translate"));

  file_util::FileEnumerator file_enumerator(
      data_dir, false, file_util::FileEnumerator::FILES,
      FILE_PATH_LITERAL("*_ORIGINAL.html"));

  FilePath original_file_path = file_enumerator.Next();
  while (!original_file_path.empty()) {
    // Locate the _TRANSLATED.html file.
    FilePath::StringType original_base = original_file_path.BaseName().value();
    LOG(INFO) << "Processing file " << original_base;
    size_t orig_index =
        original_base.rfind(FILE_PATH_LITERAL("_ORIGINAL.html"));
    ASSERT_NE(FilePath::StringType::npos, orig_index);
    FilePath::StringType translated_base = original_base.substr(0, orig_index) +
        FILE_PATH_LITERAL("_TRANSLATED.html");

    FilePath translated_file_path(original_file_path.DirName());
    translated_file_path = translated_file_path.Append(translated_base);

    ASSERT_TRUE(file_util::PathExists(translated_file_path));

    // Load the original file.
    int64 size;
    ASSERT_TRUE(file_util::GetFileSize(original_file_path, &size));
    scoped_array<char> buffer(new char[static_cast<size_t>(size) + 1]);
    ASSERT_EQ(size, file_util::ReadFile(original_file_path, buffer.get(),
                                        static_cast<int>(size)));
    buffer[static_cast<size_t>(size)] = '\0';
    LoadHTML(buffer.get());

    WebKit::WebFrame* web_frame = GetMainFrame();
    ASSERT_TRUE(web_frame);

    // Translate it.
    ReverseTextTranslator text_translator;
    PageTranslator translator(&text_translator, NULL);
    translator.TranslatePage(0, web_frame, "en", "fr");

    // Translation is asynchronous, so we need to process the pending messages
    // to make it happen.
    MessageLoop::current()->RunAllPending();

    WebKit::WebString actual_translated_contents = web_frame->contentAsMarkup();

    // Load the translated page.
    ASSERT_TRUE(file_util::GetFileSize(translated_file_path, &size));
    buffer.reset(new char[static_cast<size_t>(size) + 1]);
    ASSERT_EQ(size, file_util::ReadFile(translated_file_path, buffer.get(),
                                        static_cast<int>(size)));
    buffer[static_cast<size_t>(size)] = '\0';
    LoadHTML(buffer.get());

    web_frame = GetMainFrame();
    ASSERT_TRUE(web_frame);
    WebKit::WebString expected_translated_contents =
        web_frame->contentAsMarkup();

    EXPECT_EQ(expected_translated_contents.length(),
              actual_translated_contents.length());

    // We compare the actual and expected results by chunks of 80 chars to make
    // debugging easier.
    int max = std::min(expected_translated_contents.length(),
                       actual_translated_contents.length());
    int index = 0;
    while (index < max) {
      int len = std::min(80, max - index);
      string16 expected(expected_translated_contents.data() + index, len);
      string16 actual(actual_translated_contents.data() + index, len);
      ASSERT_EQ(expected, actual);
      index += 80;
    }

    // Iterate to the next file to test.
    original_file_path = file_enumerator.Next();
  }
}