Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: net/proxy/proxy_script_decider_unittest.cc

Issue 2315613002: Extracted NetLog class's inner enum types into their own enum classes and (Closed)
Patch Set: Ran "git cl format" on code. Much formatting ensued. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/proxy/proxy_script_decider.cc ('k') | net/proxy/proxy_service.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <vector> 5 #include <vector>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/memory/weak_ptr.h" 10 #include "base/memory/weak_ptr.h"
11 #include "base/run_loop.h" 11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
16 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
18 #include "net/base/test_completion_callback.h" 18 #include "net/base/test_completion_callback.h"
19 #include "net/dns/mock_host_resolver.h" 19 #include "net/dns/mock_host_resolver.h"
20 #include "net/log/net_log.h" 20 #include "net/log/net_log.h"
21 #include "net/log/net_log_event_type.h"
21 #include "net/log/test_net_log.h" 22 #include "net/log/test_net_log.h"
22 #include "net/log/test_net_log_entry.h" 23 #include "net/log/test_net_log_entry.h"
23 #include "net/log/test_net_log_util.h" 24 #include "net/log/test_net_log_util.h"
24 #include "net/proxy/dhcp_proxy_script_fetcher.h" 25 #include "net/proxy/dhcp_proxy_script_fetcher.h"
25 #include "net/proxy/mock_proxy_script_fetcher.h" 26 #include "net/proxy/mock_proxy_script_fetcher.h"
26 #include "net/proxy/proxy_config.h" 27 #include "net/proxy/proxy_config.h"
27 #include "net/proxy/proxy_resolver.h" 28 #include "net/proxy/proxy_resolver.h"
28 #include "net/proxy/proxy_script_decider.h" 29 #include "net/proxy/proxy_script_decider.h"
29 #include "net/proxy/proxy_script_fetcher.h" 30 #include "net/proxy/proxy_script_fetcher.h"
30 #include "net/test/gtest_util.h" 31 #include "net/test/gtest_util.h"
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); 203 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
203 EXPECT_EQ(OK, decider.Start( 204 EXPECT_EQ(OK, decider.Start(
204 config, base::TimeDelta(), true, callback.callback())); 205 config, base::TimeDelta(), true, callback.callback()));
205 EXPECT_EQ(rule.text(), decider.script_data()->utf16()); 206 EXPECT_EQ(rule.text(), decider.script_data()->utf16());
206 207
207 // Check the NetLog was filled correctly. 208 // Check the NetLog was filled correctly.
208 TestNetLogEntry::List entries; 209 TestNetLogEntry::List entries;
209 log.GetEntries(&entries); 210 log.GetEntries(&entries);
210 211
211 EXPECT_EQ(4u, entries.size()); 212 EXPECT_EQ(4u, entries.size());
213 EXPECT_TRUE(
214 LogContainsBeginEvent(entries, 0, NetLogEventType::PROXY_SCRIPT_DECIDER));
212 EXPECT_TRUE(LogContainsBeginEvent( 215 EXPECT_TRUE(LogContainsBeginEvent(
213 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 216 entries, 1, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
214 EXPECT_TRUE(LogContainsBeginEvent(
215 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
216 EXPECT_TRUE(LogContainsEndEvent( 217 EXPECT_TRUE(LogContainsEndEvent(
217 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 218 entries, 2, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
218 EXPECT_TRUE(LogContainsEndEvent( 219 EXPECT_TRUE(
219 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 220 LogContainsEndEvent(entries, 3, NetLogEventType::PROXY_SCRIPT_DECIDER));
220 221
221 EXPECT_TRUE(decider.effective_config().has_pac_url()); 222 EXPECT_TRUE(decider.effective_config().has_pac_url());
222 EXPECT_EQ(config.pac_url(), decider.effective_config().pac_url()); 223 EXPECT_EQ(config.pac_url(), decider.effective_config().pac_url());
223 } 224 }
224 225
225 // Fail downloading the custom PAC script. 226 // Fail downloading the custom PAC script.
226 TEST(ProxyScriptDeciderTest, CustomPacFails1) { 227 TEST(ProxyScriptDeciderTest, CustomPacFails1) {
227 Rules rules; 228 Rules rules;
228 RuleBasedProxyScriptFetcher fetcher(&rules); 229 RuleBasedProxyScriptFetcher fetcher(&rules);
229 DoNothingDhcpProxyScriptFetcher dhcp_fetcher; 230 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
230 231
231 ProxyConfig config; 232 ProxyConfig config;
232 config.set_pac_url(GURL("http://custom/proxy.pac")); 233 config.set_pac_url(GURL("http://custom/proxy.pac"));
233 234
234 rules.AddFailDownloadRule("http://custom/proxy.pac"); 235 rules.AddFailDownloadRule("http://custom/proxy.pac");
235 236
236 TestCompletionCallback callback; 237 TestCompletionCallback callback;
237 TestNetLog log; 238 TestNetLog log;
238 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); 239 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
239 EXPECT_EQ(kFailedDownloading, 240 EXPECT_EQ(kFailedDownloading,
240 decider.Start(config, base::TimeDelta(), true, 241 decider.Start(config, base::TimeDelta(), true,
241 callback.callback())); 242 callback.callback()));
242 EXPECT_FALSE(decider.script_data()); 243 EXPECT_FALSE(decider.script_data());
243 244
244 // Check the NetLog was filled correctly. 245 // Check the NetLog was filled correctly.
245 TestNetLogEntry::List entries; 246 TestNetLogEntry::List entries;
246 log.GetEntries(&entries); 247 log.GetEntries(&entries);
247 248
248 EXPECT_EQ(4u, entries.size()); 249 EXPECT_EQ(4u, entries.size());
250 EXPECT_TRUE(
251 LogContainsBeginEvent(entries, 0, NetLogEventType::PROXY_SCRIPT_DECIDER));
249 EXPECT_TRUE(LogContainsBeginEvent( 252 EXPECT_TRUE(LogContainsBeginEvent(
250 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 253 entries, 1, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
251 EXPECT_TRUE(LogContainsBeginEvent(
252 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
253 EXPECT_TRUE(LogContainsEndEvent( 254 EXPECT_TRUE(LogContainsEndEvent(
254 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 255 entries, 2, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
255 EXPECT_TRUE(LogContainsEndEvent( 256 EXPECT_TRUE(
256 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 257 LogContainsEndEvent(entries, 3, NetLogEventType::PROXY_SCRIPT_DECIDER));
257 258
258 EXPECT_FALSE(decider.effective_config().has_pac_url()); 259 EXPECT_FALSE(decider.effective_config().has_pac_url());
259 } 260 }
260 261
261 // Fail parsing the custom PAC script. 262 // Fail parsing the custom PAC script.
262 TEST(ProxyScriptDeciderTest, CustomPacFails2) { 263 TEST(ProxyScriptDeciderTest, CustomPacFails2) {
263 Rules rules; 264 Rules rules;
264 RuleBasedProxyScriptFetcher fetcher(&rules); 265 RuleBasedProxyScriptFetcher fetcher(&rules);
265 DoNothingDhcpProxyScriptFetcher dhcp_fetcher; 266 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
266 267
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 EXPECT_TRUE(decider.effective_config().Equals( 500 EXPECT_TRUE(decider.effective_config().Equals(
500 ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac")))); 501 ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac"))));
501 502
502 // Check the NetLog was filled correctly. 503 // Check the NetLog was filled correctly.
503 // (Note that various states are repeated since both WPAD and custom 504 // (Note that various states are repeated since both WPAD and custom
504 // PAC scripts are tried). 505 // PAC scripts are tried).
505 TestNetLogEntry::List entries; 506 TestNetLogEntry::List entries;
506 log.GetEntries(&entries); 507 log.GetEntries(&entries);
507 508
508 EXPECT_EQ(10u, entries.size()); 509 EXPECT_EQ(10u, entries.size());
509 EXPECT_TRUE(LogContainsBeginEvent( 510 EXPECT_TRUE(
510 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 511 LogContainsBeginEvent(entries, 0, NetLogEventType::PROXY_SCRIPT_DECIDER));
511 // This is the DHCP phase, which fails fetching rather than parsing, so 512 // This is the DHCP phase, which fails fetching rather than parsing, so
512 // there is no pair of SET_PAC_SCRIPT events. 513 // there is no pair of SET_PAC_SCRIPT events.
513 EXPECT_TRUE(LogContainsBeginEvent( 514 EXPECT_TRUE(LogContainsBeginEvent(
514 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 515 entries, 1, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
515 EXPECT_TRUE(LogContainsEndEvent( 516 EXPECT_TRUE(LogContainsEndEvent(
516 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 517 entries, 2, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
517 EXPECT_TRUE(LogContainsEvent( 518 EXPECT_TRUE(LogContainsEvent(
518 entries, 3, 519 entries, 3,
519 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE, 520 NetLogEventType::PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
520 NetLog::PHASE_NONE)); 521 NetLogEventPhase::NONE));
521 // This is the DNS phase, which attempts a fetch but fails. 522 // This is the DNS phase, which attempts a fetch but fails.
522 EXPECT_TRUE(LogContainsBeginEvent( 523 EXPECT_TRUE(LogContainsBeginEvent(
523 entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 524 entries, 4, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
524 EXPECT_TRUE(LogContainsEndEvent( 525 EXPECT_TRUE(LogContainsEndEvent(
525 entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 526 entries, 5, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
526 EXPECT_TRUE(LogContainsEvent( 527 EXPECT_TRUE(LogContainsEvent(
527 entries, 6, 528 entries, 6,
528 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE, 529 NetLogEventType::PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
529 NetLog::PHASE_NONE)); 530 NetLogEventPhase::NONE));
530 // Finally, the custom PAC URL phase. 531 // Finally, the custom PAC URL phase.
531 EXPECT_TRUE(LogContainsBeginEvent( 532 EXPECT_TRUE(LogContainsBeginEvent(
532 entries, 7, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 533 entries, 7, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
533 EXPECT_TRUE(LogContainsEndEvent( 534 EXPECT_TRUE(LogContainsEndEvent(
534 entries, 8, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 535 entries, 8, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
535 EXPECT_TRUE(LogContainsEndEvent( 536 EXPECT_TRUE(
536 entries, 9, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 537 LogContainsEndEvent(entries, 9, NetLogEventType::PROXY_SCRIPT_DECIDER));
537 } 538 }
538 539
539 // Fails at WPAD (downloading), and fails at custom PAC (downloading). 540 // Fails at WPAD (downloading), and fails at custom PAC (downloading).
540 TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails1) { 541 TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails1) {
541 Rules rules; 542 Rules rules;
542 RuleBasedProxyScriptFetcher fetcher(&rules); 543 RuleBasedProxyScriptFetcher fetcher(&rules);
543 DoNothingDhcpProxyScriptFetcher dhcp_fetcher; 544 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
544 545
545 ProxyConfig config; 546 ProxyConfig config;
546 config.set_auto_detect(true); 547 config.set_auto_detect(true);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 true, callback.callback())); 600 true, callback.callback()));
600 601
601 EXPECT_EQ(kFailedDownloading, callback.WaitForResult()); 602 EXPECT_EQ(kFailedDownloading, callback.WaitForResult());
602 EXPECT_FALSE(decider.script_data()); 603 EXPECT_FALSE(decider.script_data());
603 604
604 // Check the NetLog was filled correctly. 605 // Check the NetLog was filled correctly.
605 TestNetLogEntry::List entries; 606 TestNetLogEntry::List entries;
606 log.GetEntries(&entries); 607 log.GetEntries(&entries);
607 608
608 EXPECT_EQ(6u, entries.size()); 609 EXPECT_EQ(6u, entries.size());
610 EXPECT_TRUE(
611 LogContainsBeginEvent(entries, 0, NetLogEventType::PROXY_SCRIPT_DECIDER));
609 EXPECT_TRUE(LogContainsBeginEvent( 612 EXPECT_TRUE(LogContainsBeginEvent(
610 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 613 entries, 1, NetLogEventType::PROXY_SCRIPT_DECIDER_WAIT));
614 EXPECT_TRUE(LogContainsEndEvent(entries, 2,
615 NetLogEventType::PROXY_SCRIPT_DECIDER_WAIT));
611 EXPECT_TRUE(LogContainsBeginEvent( 616 EXPECT_TRUE(LogContainsBeginEvent(
612 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT)); 617 entries, 3, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
613 EXPECT_TRUE(LogContainsEndEvent( 618 EXPECT_TRUE(LogContainsEndEvent(
614 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT)); 619 entries, 4, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
615 EXPECT_TRUE(LogContainsBeginEvent( 620 EXPECT_TRUE(
616 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 621 LogContainsEndEvent(entries, 5, NetLogEventType::PROXY_SCRIPT_DECIDER));
617 EXPECT_TRUE(LogContainsEndEvent(
618 entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
619 EXPECT_TRUE(LogContainsEndEvent(
620 entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
621 } 622 }
622 623
623 // This is a copy-paste of CustomPacFails1, with the exception that we give it 624 // This is a copy-paste of CustomPacFails1, with the exception that we give it
624 // a -5 second delay instead of a 0 ms delay. This change should have no effect 625 // a -5 second delay instead of a 0 ms delay. This change should have no effect
625 // so the rest of the test is unchanged. 626 // so the rest of the test is unchanged.
626 TEST(ProxyScriptDeciderTest, CustomPacFails1_WithNegativeDelay) { 627 TEST(ProxyScriptDeciderTest, CustomPacFails1_WithNegativeDelay) {
627 Rules rules; 628 Rules rules;
628 RuleBasedProxyScriptFetcher fetcher(&rules); 629 RuleBasedProxyScriptFetcher fetcher(&rules);
629 DoNothingDhcpProxyScriptFetcher dhcp_fetcher; 630 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
630 631
631 ProxyConfig config; 632 ProxyConfig config;
632 config.set_pac_url(GURL("http://custom/proxy.pac")); 633 config.set_pac_url(GURL("http://custom/proxy.pac"));
633 634
634 rules.AddFailDownloadRule("http://custom/proxy.pac"); 635 rules.AddFailDownloadRule("http://custom/proxy.pac");
635 636
636 TestCompletionCallback callback; 637 TestCompletionCallback callback;
637 TestNetLog log; 638 TestNetLog log;
638 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); 639 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
639 EXPECT_EQ(kFailedDownloading, 640 EXPECT_EQ(kFailedDownloading,
640 decider.Start(config, base::TimeDelta::FromSeconds(-5), 641 decider.Start(config, base::TimeDelta::FromSeconds(-5),
641 true, callback.callback())); 642 true, callback.callback()));
642 EXPECT_FALSE(decider.script_data()); 643 EXPECT_FALSE(decider.script_data());
643 644
644 // Check the NetLog was filled correctly. 645 // Check the NetLog was filled correctly.
645 TestNetLogEntry::List entries; 646 TestNetLogEntry::List entries;
646 log.GetEntries(&entries); 647 log.GetEntries(&entries);
647 648
648 EXPECT_EQ(4u, entries.size()); 649 EXPECT_EQ(4u, entries.size());
650 EXPECT_TRUE(
651 LogContainsBeginEvent(entries, 0, NetLogEventType::PROXY_SCRIPT_DECIDER));
649 EXPECT_TRUE(LogContainsBeginEvent( 652 EXPECT_TRUE(LogContainsBeginEvent(
650 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 653 entries, 1, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
651 EXPECT_TRUE(LogContainsBeginEvent(
652 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
653 EXPECT_TRUE(LogContainsEndEvent( 654 EXPECT_TRUE(LogContainsEndEvent(
654 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); 655 entries, 2, NetLogEventType::PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
655 EXPECT_TRUE(LogContainsEndEvent( 656 EXPECT_TRUE(
656 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); 657 LogContainsEndEvent(entries, 3, NetLogEventType::PROXY_SCRIPT_DECIDER));
657 } 658 }
658 659
659 class SynchronousSuccessDhcpFetcher : public DhcpProxyScriptFetcher { 660 class SynchronousSuccessDhcpFetcher : public DhcpProxyScriptFetcher {
660 public: 661 public:
661 explicit SynchronousSuccessDhcpFetcher(const base::string16& expected_text) 662 explicit SynchronousSuccessDhcpFetcher(const base::string16& expected_text)
662 : gurl_("http://dhcppac/"), expected_text_(expected_text) { 663 : gurl_("http://dhcppac/"), expected_text_(expected_text) {
663 } 664 }
664 665
665 int Fetch(base::string16* utf16_text, 666 int Fetch(base::string16* utf16_text,
666 const CompletionCallback& callback) override { 667 const CompletionCallback& callback) override {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 790
790 // Run the message loop to let the DHCP fetch complete and post the results 791 // Run the message loop to let the DHCP fetch complete and post the results
791 // back. Before the fix linked to above, this would try to invoke on 792 // back. Before the fix linked to above, this would try to invoke on
792 // the callback object provided by ProxyScriptDecider after it was 793 // the callback object provided by ProxyScriptDecider after it was
793 // no longer valid. 794 // no longer valid.
794 base::RunLoop().RunUntilIdle(); 795 base::RunLoop().RunUntilIdle();
795 } 796 }
796 797
797 } // namespace 798 } // namespace
798 } // namespace net 799 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/proxy_script_decider.cc ('k') | net/proxy/proxy_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698