| OLD | NEW | 
|    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 <string> |    5 #include <string> | 
|    6  |    6  | 
|    7 #include "base/location.h" |    7 #include "base/location.h" | 
|    8 #include "base/memory/scoped_ptr.h" |    8 #include "base/memory/scoped_ptr.h" | 
|    9 #include "base/stringprintf.h" |    9 #include "base/stringprintf.h" | 
|   10 #include "sync/engine/apply_updates_command.h" |   10 #include "sync/engine/apply_updates_command.h" | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   74   entry_factory_->CreateUnappliedNewItemWithParent("parent", |   74   entry_factory_->CreateUnappliedNewItemWithParent("parent", | 
|   75                                                    DefaultBookmarkSpecifics(), |   75                                                    DefaultBookmarkSpecifics(), | 
|   76                                                    root_server_id); |   76                                                    root_server_id); | 
|   77   entry_factory_->CreateUnappliedNewItemWithParent("child", |   77   entry_factory_->CreateUnappliedNewItemWithParent("child", | 
|   78                                                    DefaultBookmarkSpecifics(), |   78                                                    DefaultBookmarkSpecifics(), | 
|   79                                                    "parent"); |   79                                                    "parent"); | 
|   80  |   80  | 
|   81   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |   81   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|   82   apply_updates_command_.ExecuteImpl(session()); |   82   apply_updates_command_.ExecuteImpl(session()); | 
|   83  |   83  | 
|   84   sessions::StatusController* status = session()->mutable_status_controller(); |   84   const sessions::StatusController& status = session()->status_controller(); | 
|   85  |   85   EXPECT_EQ(0, status.num_simple_conflicts()) | 
|   86   EXPECT_EQ(0, status->num_simple_conflicts()) |  | 
|   87       << "Simple update shouldn't result in conflicts"; |   86       << "Simple update shouldn't result in conflicts"; | 
|   88   EXPECT_EQ(0, status->num_encryption_conflicts()) |   87   EXPECT_EQ(0, status.num_encryption_conflicts()) | 
|   89       << "Simple update shouldn't result in conflicts"; |   88       << "Simple update shouldn't result in conflicts"; | 
|   90   EXPECT_EQ(0, status->num_hierarchy_conflicts()) |   89   EXPECT_EQ(0, status.num_hierarchy_conflicts()) | 
|   91       << "Simple update shouldn't result in conflicts"; |   90       << "Simple update shouldn't result in conflicts"; | 
|   92   sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |   91   EXPECT_EQ(2, status.num_updates_applied()) | 
|   93   ASSERT_TRUE(status->update_progress()); |  | 
|   94   EXPECT_EQ(2, status->update_progress()->AppliedUpdatesSize()) |  | 
|   95       << "All updates should have been attempted"; |  | 
|   96   EXPECT_EQ(2, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|   97       << "All items should have been successfully applied"; |   92       << "All items should have been successfully applied"; | 
|   98 } |   93 } | 
|   99  |   94  | 
|  100 TEST_F(ApplyUpdatesCommandTest, UpdateWithChildrenBeforeParents) { |   95 TEST_F(ApplyUpdatesCommandTest, UpdateWithChildrenBeforeParents) { | 
|  101   // Set a bunch of updates which are difficult to apply in the order |   96   // Set a bunch of updates which are difficult to apply in the order | 
|  102   // they're received due to dependencies on other unseen items. |   97   // they're received due to dependencies on other unseen items. | 
|  103   string root_server_id = syncable::GetNullId().GetServerId(); |   98   string root_server_id = syncable::GetNullId().GetServerId(); | 
|  104   entry_factory_->CreateUnappliedNewItemWithParent( |   99   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  105       "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); |  100       "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); | 
|  106   entry_factory_->CreateUnappliedNewItemWithParent( |  101   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  107       "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); |  102       "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); | 
|  108   entry_factory_->CreateUnappliedNewItemWithParent( |  103   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  109       "parent", DefaultBookmarkSpecifics(), root_server_id); |  104       "parent", DefaultBookmarkSpecifics(), root_server_id); | 
|  110   entry_factory_->CreateUnappliedNewItemWithParent( |  105   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  111       "a_child_created_second", DefaultBookmarkSpecifics(), "parent"); |  106       "a_child_created_second", DefaultBookmarkSpecifics(), "parent"); | 
|  112   entry_factory_->CreateUnappliedNewItemWithParent( |  107   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  113       "x_child_created_second", DefaultBookmarkSpecifics(), "parent"); |  108       "x_child_created_second", DefaultBookmarkSpecifics(), "parent"); | 
|  114  |  109  | 
|  115   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  110   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  116   apply_updates_command_.ExecuteImpl(session()); |  111   apply_updates_command_.ExecuteImpl(session()); | 
|  117  |  112  | 
|  118   sessions::StatusController* status = session()->mutable_status_controller(); |  113   const sessions::StatusController& status = session()->status_controller(); | 
|  119   EXPECT_EQ(0, status->num_simple_conflicts()) |  114   EXPECT_EQ(0, status.num_simple_conflicts()) | 
|  120       << "Simple update shouldn't result in conflicts, even if out-of-order"; |  115       << "Simple update shouldn't result in conflicts, even if out-of-order"; | 
|  121   sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |  116   EXPECT_EQ(5, status.num_updates_applied()) | 
|  122   ASSERT_TRUE(status->update_progress()); |  | 
|  123   EXPECT_EQ(5, status->update_progress()->AppliedUpdatesSize()) |  | 
|  124       << "All updates should have been attempted"; |  | 
|  125   EXPECT_EQ(5, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|  126       << "All updates should have been successfully applied"; |  117       << "All updates should have been successfully applied"; | 
|  127 } |  118 } | 
|  128  |  119  | 
|  129 // Runs the ApplyUpdatesCommand on an item that has both local and remote |  120 // Runs the ApplyUpdatesCommand on an item that has both local and remote | 
|  130 // modifications (IS_UNSYNCED and IS_UNAPPLIED_UPDATE).  We expect the command |  121 // modifications (IS_UNSYNCED and IS_UNAPPLIED_UPDATE).  We expect the command | 
|  131 // to detect that this update can't be applied because it is in a CONFLICT |  122 // to detect that this update can't be applied because it is in a CONFLICT | 
|  132 // state. |  123 // state. | 
|  133 TEST_F(ApplyUpdatesCommandTest, SimpleConflict) { |  124 TEST_F(ApplyUpdatesCommandTest, SimpleConflict) { | 
|  134   entry_factory_->CreateUnappliedAndUnsyncedItem("item", BOOKMARKS); |  125   entry_factory_->CreateUnappliedAndUnsyncedItem("item", BOOKMARKS); | 
|  135  |  126  | 
|  136   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  127   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  137   apply_updates_command_.ExecuteImpl(session()); |  128   apply_updates_command_.ExecuteImpl(session()); | 
|  138  |  129  | 
|  139   sessions::StatusController* status = session()->mutable_status_controller(); |  130   const sessions::StatusController& status = session()->status_controller(); | 
|  140   EXPECT_EQ(1, status->num_simple_conflicts()) |  131   EXPECT_EQ(1, status.num_simple_conflicts()) | 
|  141       << "Unsynced and unapplied item should be a simple conflict"; |  132       << "Unsynced and unapplied item should be a simple conflict"; | 
|  142 } |  133 } | 
|  143  |  134  | 
|  144 // Runs the ApplyUpdatesCommand on an item that has both local and remote |  135 // Runs the ApplyUpdatesCommand on an item that has both local and remote | 
|  145 // modifications *and* the remote modification cannot be applied without |  136 // modifications *and* the remote modification cannot be applied without | 
|  146 // violating the tree constraints.  We expect the command to detect that this |  137 // violating the tree constraints.  We expect the command to detect that this | 
|  147 // update can't be applied and that this situation can't be resolved with the |  138 // update can't be applied and that this situation can't be resolved with the | 
|  148 // simple conflict processing logic; it is in a CONFLICT_HIERARCHY state. |  139 // simple conflict processing logic; it is in a CONFLICT_HIERARCHY state. | 
|  149 TEST_F(ApplyUpdatesCommandTest, HierarchyAndSimpleConflict) { |  140 TEST_F(ApplyUpdatesCommandTest, HierarchyAndSimpleConflict) { | 
|  150   // Create a simply-conflicting item.  It will start with valid parent ids. |  141   // Create a simply-conflicting item.  It will start with valid parent ids. | 
|  151   int64 handle = entry_factory_->CreateUnappliedAndUnsyncedItem( |  142   int64 handle = entry_factory_->CreateUnappliedAndUnsyncedItem( | 
|  152       "orphaned_by_server", BOOKMARKS); |  143       "orphaned_by_server", BOOKMARKS); | 
|  153   { |  144   { | 
|  154     // Manually set the SERVER_PARENT_ID to bad value. |  145     // Manually set the SERVER_PARENT_ID to bad value. | 
|  155     // A bad parent indicates a hierarchy conflict. |  146     // A bad parent indicates a hierarchy conflict. | 
|  156     WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |  147     WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 
|  157     MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); |  148     MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); | 
|  158     ASSERT_TRUE(entry.good()); |  149     ASSERT_TRUE(entry.good()); | 
|  159  |  150  | 
|  160     entry.Put(syncable::SERVER_PARENT_ID, |  151     entry.Put(syncable::SERVER_PARENT_ID, | 
|  161               TestIdFactory::MakeServer("bogus_parent")); |  152               TestIdFactory::MakeServer("bogus_parent")); | 
|  162   } |  153   } | 
|  163  |  154  | 
|  164   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  155   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  165   apply_updates_command_.ExecuteImpl(session()); |  156   apply_updates_command_.ExecuteImpl(session()); | 
|  166  |  157  | 
|  167   sessions::StatusController* status = session()->mutable_status_controller(); |  158   const sessions::StatusController& status = session()->status_controller(); | 
|  168  |  159  | 
|  169   // An update that is both a simple conflict and a hierarchy conflict should be |  160   // An update that is both a simple conflict and a hierarchy conflict should be | 
|  170   // treated as a hierarchy conflict. |  161   // treated as a hierarchy conflict. | 
|  171   EXPECT_EQ(1, status->num_hierarchy_conflicts()); |  162   EXPECT_EQ(1, status.num_hierarchy_conflicts()); | 
|  172   EXPECT_EQ(0, status->num_simple_conflicts()); |  163   EXPECT_EQ(0, status.num_simple_conflicts()); | 
|  173  |  | 
|  174   sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |  | 
|  175   EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()); |  | 
|  176 } |  164 } | 
|  177  |  165  | 
|  178  |  166  | 
|  179 // Runs the ApplyUpdatesCommand on an item with remote modifications that would |  167 // Runs the ApplyUpdatesCommand on an item with remote modifications that would | 
|  180 // create a directory loop if the update were applied.  We expect the command to |  168 // create a directory loop if the update were applied.  We expect the command to | 
|  181 // detect that this update can't be applied because it is in a |  169 // detect that this update can't be applied because it is in a | 
|  182 // CONFLICT_HIERARCHY state. |  170 // CONFLICT_HIERARCHY state. | 
|  183 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDirectoryLoop) { |  171 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDirectoryLoop) { | 
|  184   // Item 'X' locally has parent of 'root'.  Server is updating it to have |  172   // Item 'X' locally has parent of 'root'.  Server is updating it to have | 
|  185   // parent of 'Y'. |  173   // parent of 'Y'. | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|  203       BOOKMARKS, NULL); |  191       BOOKMARKS, NULL); | 
|  204  |  192  | 
|  205   // If the server's update were applied, we would have X be a child of Y, and Y |  193   // If the server's update were applied, we would have X be a child of Y, and Y | 
|  206   // as a child of X.  That's a directory loop.  The UpdateApplicator should |  194   // as a child of X.  That's a directory loop.  The UpdateApplicator should | 
|  207   // prevent the update from being applied and note that this is a hierarchy |  195   // prevent the update from being applied and note that this is a hierarchy | 
|  208   // conflict. |  196   // conflict. | 
|  209  |  197  | 
|  210   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  198   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  211   apply_updates_command_.ExecuteImpl(session()); |  199   apply_updates_command_.ExecuteImpl(session()); | 
|  212  |  200  | 
|  213   sessions::StatusController* status = session()->mutable_status_controller(); |  201   const sessions::StatusController& status = session()->status_controller(); | 
|  214  |  202  | 
|  215   // This should count as a hierarchy conflict. |  203   // This should count as a hierarchy conflict. | 
|  216   EXPECT_EQ(1, status->num_hierarchy_conflicts()); |  204   EXPECT_EQ(1, status.num_hierarchy_conflicts()); | 
|  217   EXPECT_EQ(0, status->num_simple_conflicts()); |  205   EXPECT_EQ(0, status.num_simple_conflicts()); | 
|  218  |  | 
|  219   sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |  | 
|  220   EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()); |  | 
|  221 } |  206 } | 
|  222  |  207  | 
|  223 // Runs the ApplyUpdatesCommand on a directory where the server sent us an |  208 // Runs the ApplyUpdatesCommand on a directory where the server sent us an | 
|  224 // update to add a child to a locally deleted (and unsynced) parent.  We expect |  209 // update to add a child to a locally deleted (and unsynced) parent.  We expect | 
|  225 // the command to not apply the update and to indicate the update is in a |  210 // the command to not apply the update and to indicate the update is in a | 
|  226 // CONFLICT_HIERARCHY state. |  211 // CONFLICT_HIERARCHY state. | 
|  227 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeletedParent) { |  212 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeletedParent) { | 
|  228   // Create a locally deleted parent item. |  213   // Create a locally deleted parent item. | 
|  229   int64 parent_handle; |  214   int64 parent_handle; | 
|  230   entry_factory_->CreateUnsyncedItem( |  215   entry_factory_->CreateUnsyncedItem( | 
|  231       Id::CreateFromServerId("parent"), TestIdFactory::root(), |  216       Id::CreateFromServerId("parent"), TestIdFactory::root(), | 
|  232       "parent", true, BOOKMARKS, &parent_handle); |  217       "parent", true, BOOKMARKS, &parent_handle); | 
|  233   { |  218   { | 
|  234     WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |  219     WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 
|  235     MutableEntry entry(&trans, syncable::GET_BY_HANDLE, parent_handle); |  220     MutableEntry entry(&trans, syncable::GET_BY_HANDLE, parent_handle); | 
|  236     entry.Put(syncable::IS_DEL, true); |  221     entry.Put(syncable::IS_DEL, true); | 
|  237   } |  222   } | 
|  238  |  223  | 
|  239   // Create an incoming child from the server. |  224   // Create an incoming child from the server. | 
|  240   entry_factory_->CreateUnappliedNewItemWithParent( |  225   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  241       "child", DefaultBookmarkSpecifics(), "parent"); |  226       "child", DefaultBookmarkSpecifics(), "parent"); | 
|  242  |  227  | 
|  243   // The server's update may seem valid to some other client, but on this client |  228   // The server's update may seem valid to some other client, but on this client | 
|  244   // that new item's parent no longer exists.  The update should not be applied |  229   // that new item's parent no longer exists.  The update should not be applied | 
|  245   // and the update applicator should indicate this is a hierarchy conflict. |  230   // and the update applicator should indicate this is a hierarchy conflict. | 
|  246  |  231  | 
|  247   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  232   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  248   apply_updates_command_.ExecuteImpl(session()); |  233   apply_updates_command_.ExecuteImpl(session()); | 
|  249  |  234  | 
|  250   sessions::StatusController* status = session()->mutable_status_controller(); |  235   const sessions::StatusController& status = session()->status_controller(); | 
|  251   EXPECT_EQ(1, status->num_hierarchy_conflicts()); |  236   EXPECT_EQ(1, status.num_hierarchy_conflicts()); | 
|  252   EXPECT_EQ(0, status->num_simple_conflicts()); |  237   EXPECT_EQ(0, status.num_simple_conflicts()); | 
|  253 } |  238 } | 
|  254  |  239  | 
|  255 // Runs the ApplyUpdatesCommand on a directory where the server is trying to |  240 // Runs the ApplyUpdatesCommand on a directory where the server is trying to | 
|  256 // delete a folder that has a recently added (and unsynced) child.  We expect |  241 // delete a folder that has a recently added (and unsynced) child.  We expect | 
|  257 // the command to not apply the update because it is in a CONFLICT_HIERARCHY |  242 // the command to not apply the update because it is in a CONFLICT_HIERARCHY | 
|  258 // state. |  243 // state. | 
|  259 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeleteNonEmptyDirectory) { |  244 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeleteNonEmptyDirectory) { | 
|  260   // Create a server-deleted directory. |  245   // Create a server-deleted directory. | 
|  261   { |  246   { | 
|  262     // Create it as a child of root node. |  247     // Create it as a child of root node. | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|  278   entry_factory_->CreateUnsyncedItem( |  263   entry_factory_->CreateUnsyncedItem( | 
|  279       TestIdFactory::MakeServer("child"), TestIdFactory::MakeServer("parent"), |  264       TestIdFactory::MakeServer("child"), TestIdFactory::MakeServer("parent"), | 
|  280       "child", false, BOOKMARKS, NULL); |  265       "child", false, BOOKMARKS, NULL); | 
|  281  |  266  | 
|  282   // The server's request to delete the directory must be ignored, otherwise our |  267   // The server's request to delete the directory must be ignored, otherwise our | 
|  283   // unsynced new child would be orphaned.  This is a hierarchy conflict. |  268   // unsynced new child would be orphaned.  This is a hierarchy conflict. | 
|  284  |  269  | 
|  285   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  270   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  286   apply_updates_command_.ExecuteImpl(session()); |  271   apply_updates_command_.ExecuteImpl(session()); | 
|  287  |  272  | 
|  288   sessions::StatusController* status = session()->mutable_status_controller(); |  273   const sessions::StatusController& status = session()->status_controller(); | 
|  289   // This should count as a hierarchy conflict. |  274   // This should count as a hierarchy conflict. | 
|  290   EXPECT_EQ(1, status->num_hierarchy_conflicts()); |  275   EXPECT_EQ(1, status.num_hierarchy_conflicts()); | 
|  291   EXPECT_EQ(0, status->num_simple_conflicts()); |  276   EXPECT_EQ(0, status.num_simple_conflicts()); | 
|  292 } |  277 } | 
|  293  |  278  | 
|  294 // Runs the ApplyUpdatesCommand on a server-created item that has a locally |  279 // Runs the ApplyUpdatesCommand on a server-created item that has a locally | 
|  295 // unknown parent.  We expect the command to not apply the update because the |  280 // unknown parent.  We expect the command to not apply the update because the | 
|  296 // item is in a CONFLICT_HIERARCHY state. |  281 // item is in a CONFLICT_HIERARCHY state. | 
|  297 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictUnknownParent) { |  282 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictUnknownParent) { | 
|  298   // We shouldn't be able to do anything with either of these items. |  283   // We shouldn't be able to do anything with either of these items. | 
|  299   entry_factory_->CreateUnappliedNewItemWithParent( |  284   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  300       "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); |  285       "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); | 
|  301   entry_factory_->CreateUnappliedNewItemWithParent( |  286   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  302       "some_other_item", DefaultBookmarkSpecifics(), "some_item"); |  287       "some_other_item", DefaultBookmarkSpecifics(), "some_item"); | 
|  303  |  288  | 
|  304   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  289   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  305   apply_updates_command_.ExecuteImpl(session()); |  290   apply_updates_command_.ExecuteImpl(session()); | 
|  306  |  291  | 
|  307   sessions::StatusController* status = session()->mutable_status_controller(); |  292   const sessions::StatusController& status = session()->status_controller(); | 
|  308  |  293   EXPECT_EQ(0, status.num_simple_conflicts()) | 
|  309   EXPECT_EQ(0, status->num_simple_conflicts()) |  | 
|  310       << "Updates with unknown parent should not be treated as 'simple'" |  294       << "Updates with unknown parent should not be treated as 'simple'" | 
|  311       << " conflicts"; |  295       << " conflicts"; | 
|  312   EXPECT_EQ(2, status->num_hierarchy_conflicts()) |  296   EXPECT_EQ(2, status.num_hierarchy_conflicts()) | 
|  313       << "All updates with an unknown ancestors should be in conflict"; |  297       << "All updates with an unknown ancestors should be in conflict"; | 
|  314  |  298   EXPECT_EQ(0, status.num_updates_applied()) | 
|  315   sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |  | 
|  316   ASSERT_TRUE(status->update_progress()); |  | 
|  317   EXPECT_EQ(2, status->update_progress()->AppliedUpdatesSize()) |  | 
|  318       << "All updates should have been attempted"; |  | 
|  319   EXPECT_EQ(0, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|  320       << "No item with an unknown ancestor should be applied"; |  299       << "No item with an unknown ancestor should be applied"; | 
|  321 } |  300 } | 
|  322  |  301  | 
|  323 TEST_F(ApplyUpdatesCommandTest, ItemsBothKnownAndUnknown) { |  302 TEST_F(ApplyUpdatesCommandTest, ItemsBothKnownAndUnknown) { | 
|  324   // See what happens when there's a mixture of good and bad updates. |  303   // See what happens when there's a mixture of good and bad updates. | 
|  325   string root_server_id = syncable::GetNullId().GetServerId(); |  304   string root_server_id = syncable::GetNullId().GetServerId(); | 
|  326   entry_factory_->CreateUnappliedNewItemWithParent( |  305   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  327       "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); |  306       "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); | 
|  328   entry_factory_->CreateUnappliedNewItemWithParent( |  307   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  329       "first_known_item", DefaultBookmarkSpecifics(), root_server_id); |  308       "first_known_item", DefaultBookmarkSpecifics(), root_server_id); | 
|  330   entry_factory_->CreateUnappliedNewItemWithParent( |  309   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  331       "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); |  310       "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); | 
|  332   entry_factory_->CreateUnappliedNewItemWithParent( |  311   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  333       "second_known_item", DefaultBookmarkSpecifics(), "first_known_item"); |  312       "second_known_item", DefaultBookmarkSpecifics(), "first_known_item"); | 
|  334   entry_factory_->CreateUnappliedNewItemWithParent( |  313   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  335       "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item"); |  314       "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item"); | 
|  336   entry_factory_->CreateUnappliedNewItemWithParent( |  315   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  337       "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id); |  316       "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id); | 
|  338  |  317  | 
|  339   ExpectGroupToChange(apply_updates_command_, GROUP_UI); |  318   ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 
|  340   apply_updates_command_.ExecuteImpl(session()); |  319   apply_updates_command_.ExecuteImpl(session()); | 
|  341  |  320  | 
|  342   sessions::StatusController* status = session()->mutable_status_controller(); |  321   const sessions::StatusController& status = session()->status_controller(); | 
|  343  |  322   EXPECT_EQ(2, status.num_hierarchy_conflicts()) | 
|  344   EXPECT_EQ(2, status->num_hierarchy_conflicts()) |  | 
|  345       << "The updates with unknown ancestors should be in conflict"; |  323       << "The updates with unknown ancestors should be in conflict"; | 
|  346  |  324   EXPECT_EQ(4, status.num_updates_applied()) | 
|  347   sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |  | 
|  348   ASSERT_TRUE(status->update_progress()); |  | 
|  349   EXPECT_EQ(6, status->update_progress()->AppliedUpdatesSize()) |  | 
|  350       << "All updates should have been attempted"; |  | 
|  351   EXPECT_EQ(4, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|  352       << "The updates with known ancestors should be successfully applied"; |  325       << "The updates with known ancestors should be successfully applied"; | 
|  353 } |  326 } | 
|  354  |  327  | 
|  355 TEST_F(ApplyUpdatesCommandTest, DecryptablePassword) { |  328 TEST_F(ApplyUpdatesCommandTest, DecryptablePassword) { | 
|  356   // Decryptable password updates should be applied. |  329   // Decryptable password updates should be applied. | 
|  357   Cryptographer* cryptographer; |  330   Cryptographer* cryptographer; | 
|  358   { |  331   { | 
|  359     // Storing the cryptographer separately is bad, but for this test we |  332     // Storing the cryptographer separately is bad, but for this test we | 
|  360     // know it's safe. |  333     // know it's safe. | 
|  361     syncable::ReadTransaction trans(FROM_HERE, directory()); |  334     syncable::ReadTransaction trans(FROM_HERE, directory()); | 
|  362     cryptographer = directory()->GetCryptographer(&trans); |  335     cryptographer = directory()->GetCryptographer(&trans); | 
|  363   } |  336   } | 
|  364  |  337  | 
|  365   KeyParams params = {"localhost", "dummy", "foobar"}; |  338   KeyParams params = {"localhost", "dummy", "foobar"}; | 
|  366   cryptographer->AddKey(params); |  339   cryptographer->AddKey(params); | 
|  367  |  340  | 
|  368   sync_pb::EntitySpecifics specifics; |  341   sync_pb::EntitySpecifics specifics; | 
|  369   sync_pb::PasswordSpecificsData data; |  342   sync_pb::PasswordSpecificsData data; | 
|  370   data.set_origin("http://example.com"); |  343   data.set_origin("http://example.com"); | 
|  371  |  344  | 
|  372   cryptographer->Encrypt(data, |  345   cryptographer->Encrypt(data, | 
|  373                          specifics.mutable_password()->mutable_encrypted()); |  346                          specifics.mutable_password()->mutable_encrypted()); | 
|  374   entry_factory_->CreateUnappliedNewItem("item", specifics, false); |  347   entry_factory_->CreateUnappliedNewItem("item", specifics, false); | 
|  375  |  348  | 
|  376   ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD); |  349   ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD); | 
|  377   apply_updates_command_.ExecuteImpl(session()); |  350   apply_updates_command_.ExecuteImpl(session()); | 
|  378  |  351  | 
|  379   sessions::StatusController* status = session()->mutable_status_controller(); |  352   const sessions::StatusController& status = session()->status_controller(); | 
|  380  |  353   EXPECT_EQ(0, status.num_simple_conflicts()) | 
|  381   EXPECT_EQ(0, status->num_simple_conflicts()) |  | 
|  382       << "No update should be in conflict because they're all decryptable"; |  354       << "No update should be in conflict because they're all decryptable"; | 
|  383  |  355   EXPECT_EQ(1, status.num_updates_applied()) | 
|  384   sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSWORD); |  | 
|  385   ASSERT_TRUE(status->update_progress()); |  | 
|  386   EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()) |  | 
|  387       << "All updates should have been attempted"; |  | 
|  388   EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|  389       << "The updates that can be decrypted should be applied"; |  356       << "The updates that can be decrypted should be applied"; | 
|  390 } |  357 } | 
|  391  |  358  | 
|  392 TEST_F(ApplyUpdatesCommandTest, UndecryptableData) { |  359 TEST_F(ApplyUpdatesCommandTest, UndecryptableData) { | 
|  393   // Undecryptable updates should not be applied. |  360   // Undecryptable updates should not be applied. | 
|  394   sync_pb::EntitySpecifics encrypted_bookmark; |  361   sync_pb::EntitySpecifics encrypted_bookmark; | 
|  395   encrypted_bookmark.mutable_encrypted(); |  362   encrypted_bookmark.mutable_encrypted(); | 
|  396   AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark); |  363   AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark); | 
|  397   string root_server_id = syncable::GetNullId().GetServerId(); |  364   string root_server_id = syncable::GetNullId().GetServerId(); | 
|  398   entry_factory_->CreateUnappliedNewItemWithParent( |  365   entry_factory_->CreateUnappliedNewItemWithParent( | 
|  399       "folder", encrypted_bookmark, root_server_id); |  366       "folder", encrypted_bookmark, root_server_id); | 
|  400   entry_factory_->CreateUnappliedNewItem("item2", encrypted_bookmark, false); |  367   entry_factory_->CreateUnappliedNewItem("item2", encrypted_bookmark, false); | 
|  401   sync_pb::EntitySpecifics encrypted_password; |  368   sync_pb::EntitySpecifics encrypted_password; | 
|  402   encrypted_password.mutable_password(); |  369   encrypted_password.mutable_password(); | 
|  403   entry_factory_->CreateUnappliedNewItem("item3", encrypted_password, false); |  370   entry_factory_->CreateUnappliedNewItem("item3", encrypted_password, false); | 
|  404  |  371  | 
|  405   ExpectGroupsToChange(apply_updates_command_, GROUP_UI, GROUP_PASSWORD); |  372   ExpectGroupsToChange(apply_updates_command_, GROUP_UI, GROUP_PASSWORD); | 
|  406   apply_updates_command_.ExecuteImpl(session()); |  373   apply_updates_command_.ExecuteImpl(session()); | 
|  407  |  374  | 
|  408   sessions::StatusController* status = session()->mutable_status_controller(); |  375   const sessions::StatusController& status = session()->status_controller(); | 
|  409   EXPECT_TRUE(status->HasConflictingUpdates()) |  376   EXPECT_TRUE(status.HasConflictingUpdates()) | 
|  410     << "Updates that can't be decrypted should trigger the syncer to have " |  377       << "Updates that can't be decrypted should trigger the syncer to have " | 
|  411     << "conflicting updates."; |  378       << "conflicting updates."; | 
|  412   EXPECT_EQ(0, status->num_simple_conflicts()) |  379   EXPECT_EQ(0, status.num_simple_conflicts()) | 
|  413       << "Updates that can't be decrypted should not be in regular conflict"; |  380       << "Updates that can't be decrypted should not be in regular conflict"; | 
|  414   EXPECT_EQ(3, status->num_encryption_conflicts()) |  381   EXPECT_EQ(3, status.num_encryption_conflicts()) | 
|  415       << "Updates that can't be decrypted should be in encryption conflict"; |  382       << "Updates that can't be decrypted should be in encryption conflict"; | 
|  416   { |  383   EXPECT_EQ(0, status.num_updates_applied()) | 
|  417     sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |  384       << "No update that can't be decrypted should be applied"; | 
|  418     ASSERT_TRUE(status->update_progress()); |  | 
|  419     EXPECT_EQ(2, status->update_progress()->AppliedUpdatesSize()) |  | 
|  420         << "All updates should have been attempted"; |  | 
|  421     EXPECT_EQ(0, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|  422         << "No update that can't be decrypted should be applied"; |  | 
|  423   } |  | 
|  424   { |  | 
|  425     sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSWORD); |  | 
|  426     ASSERT_TRUE(status->update_progress()); |  | 
|  427     EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()) |  | 
|  428         << "All updates should have been attempted"; |  | 
|  429     EXPECT_EQ(0, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|  430         << "No update that can't be decrypted should be applied"; |  | 
|  431   } |  | 
|  432 } |  385 } | 
|  433  |  386  | 
|  434 TEST_F(ApplyUpdatesCommandTest, SomeUndecryptablePassword) { |  387 TEST_F(ApplyUpdatesCommandTest, SomeUndecryptablePassword) { | 
|  435   Cryptographer* cryptographer; |  388   Cryptographer* cryptographer; | 
|  436   // Only decryptable password updates should be applied. |  389   // Only decryptable password updates should be applied. | 
|  437   { |  390   { | 
|  438     sync_pb::EntitySpecifics specifics; |  391     sync_pb::EntitySpecifics specifics; | 
|  439     sync_pb::PasswordSpecificsData data; |  392     sync_pb::PasswordSpecificsData data; | 
|  440     data.set_origin("http://example.com/1"); |  393     data.set_origin("http://example.com/1"); | 
|  441     { |  394     { | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
|  461     data.set_origin("http://example.com/2"); |  414     data.set_origin("http://example.com/2"); | 
|  462  |  415  | 
|  463     other_cryptographer.Encrypt(data, |  416     other_cryptographer.Encrypt(data, | 
|  464         specifics.mutable_password()->mutable_encrypted()); |  417         specifics.mutable_password()->mutable_encrypted()); | 
|  465     entry_factory_->CreateUnappliedNewItem("item2", specifics, false); |  418     entry_factory_->CreateUnappliedNewItem("item2", specifics, false); | 
|  466   } |  419   } | 
|  467  |  420  | 
|  468   ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD); |  421   ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD); | 
|  469   apply_updates_command_.ExecuteImpl(session()); |  422   apply_updates_command_.ExecuteImpl(session()); | 
|  470  |  423  | 
|  471   sessions::StatusController* status = session()->mutable_status_controller(); |  424   const sessions::StatusController& status = session()->status_controller(); | 
|  472   EXPECT_TRUE(status->HasConflictingUpdates()) |  425   EXPECT_TRUE(status.HasConflictingUpdates()) | 
|  473     << "Updates that can't be decrypted should trigger the syncer to have " |  426       << "Updates that can't be decrypted should trigger the syncer to have " | 
|  474     << "conflicting updates."; |  427       << "conflicting updates."; | 
|  475   { |  428   EXPECT_EQ(0, status.num_simple_conflicts()) | 
|  476     EXPECT_EQ(0, status->num_simple_conflicts()) |  429       << "The updates that can't be decrypted should not be in regular " | 
|  477         << "The updates that can't be decrypted should not be in regular " |  430       << "conflict"; | 
|  478         << "conflict"; |  431   EXPECT_EQ(1, status.num_encryption_conflicts()) | 
|  479     EXPECT_EQ(1, status->num_encryption_conflicts()) |  432       << "The updates that can't be decrypted should be in encryption " | 
|  480         << "The updates that can't be decrypted should be in encryption " |  433       << "conflict"; | 
|  481         << "conflict"; |  434   EXPECT_EQ(1, status.num_updates_applied()) | 
|  482  |  435       << "The undecryptable password update shouldn't be applied"; | 
|  483     sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSWORD); |  | 
|  484     ASSERT_TRUE(status->update_progress()); |  | 
|  485     EXPECT_EQ(2, status->update_progress()->AppliedUpdatesSize()) |  | 
|  486         << "All updates should have been attempted"; |  | 
|  487     EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) |  | 
|  488         << "The undecryptable password update shouldn't be applied"; |  | 
|  489   } |  | 
|  490 } |  436 } | 
|  491  |  437  | 
|  492 }  // namespace syncer |  438 }  // namespace syncer | 
| OLD | NEW |