| // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:analysis_server/src/watch_manager.dart'; |
| import 'package:analyzer/file_system/file_system.dart'; |
| import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| import 'package:watcher/watcher.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(WatchManagerTest); |
| defineReflectiveTests(WatchNodeTest); |
| }); |
| } |
| |
| /** |
| * Tokens that can be used for testing purposes. |
| */ |
| class Token { |
| /** |
| * A name used for debugging. |
| */ |
| final String name; |
| |
| /** |
| * Initialize a newly created token to have the given name. |
| */ |
| Token(this.name); |
| |
| @override |
| String toString() => name; |
| } |
| |
| /** |
| * A listener that captures the state of watch events so that they can be |
| * tested. |
| */ |
| class WatchListener { |
| /** |
| * The event that was passed to the listener method. |
| */ |
| WatchEvent event; |
| |
| /** |
| * The tokens that were passed to the listener method. |
| */ |
| List<Token> tokens; |
| |
| /** |
| * Clear the state so that we can distinguish between not receiving an event |
| * and receiving the wrong event. |
| */ |
| void clear() { |
| this.event = null; |
| this.tokens = null; |
| } |
| |
| /** |
| * The listener method. |
| */ |
| void handleWatchEvent(WatchEvent event, List<Token> tokens) { |
| this.event = event; |
| this.tokens = tokens; |
| } |
| } |
| |
| @reflectiveTest |
| class WatchManagerTest extends Object with ResourceProviderMixin { |
| WatchListener listener; |
| WatchManager<Token> manager; |
| |
| void setUp() { |
| listener = new WatchListener(); |
| manager = |
| new WatchManager<Token>(resourceProvider, listener.handleWatchEvent); |
| } |
| |
| Future test_addFolder_folderAndSubfolder() async { |
| Folder topFolder = getFolder('/a/b'); |
| Folder childFolder = getFolder('/a/b/c/d'); |
| Token topToken = new Token('topToken'); |
| Token childToken = new Token('childToken'); |
| manager.addFolder(topFolder, topToken); |
| manager.addFolder(childFolder, childToken); |
| |
| File newFile1 = newFile('/a/b/c/lib.dart'); |
| await _expectEvent(ChangeType.ADD, newFile1.path, [topToken]); |
| |
| File newFile2 = newFile('/a/b/c/d/lib.dart'); |
| return _expectEvent(ChangeType.ADD, newFile2.path, [topToken, childToken]); |
| } |
| |
| Future test_addFolder_singleFolder_multipleTokens() { |
| Folder folder = getFolder('/a/b'); |
| Token token1 = new Token('token1'); |
| Token token2 = new Token('token2'); |
| manager.addFolder(folder, token1); |
| manager.addFolder(folder, token2); |
| |
| File addedFile = newFile('/a/b/lib.dart'); |
| return _expectEvent(ChangeType.ADD, addedFile.path, [token1, token2]); |
| } |
| |
| Future test_addFolder_singleFolder_singleToken() async { |
| Folder folder = getFolder('/a/b'); |
| Token token = new Token('token'); |
| manager.addFolder(folder, token); |
| |
| Folder addedFolder = newFolder('/a/b/c'); |
| await _expectEvent(ChangeType.ADD, addedFolder.path, [token]); |
| |
| File addedFile = newFile('/a/b/c/lib.dart'); |
| return _expectEvent(ChangeType.ADD, addedFile.path, [token]); |
| } |
| |
| Future test_addFolder_unrelatedFolders() async { |
| Folder folder1 = getFolder('/a/b'); |
| Folder folder2 = getFolder('/c/d'); |
| Token token1 = new Token('token1'); |
| Token token2 = new Token('token2'); |
| manager.addFolder(folder1, token1); |
| manager.addFolder(folder2, token2); |
| |
| File newFile1 = newFile('/a/b/lib.dart'); |
| await _expectEvent(ChangeType.ADD, newFile1.path, [token1]); |
| |
| File newFile2 = newFile('/c/d/lib.dart'); |
| return _expectEvent(ChangeType.ADD, newFile2.path, [token2]); |
| } |
| |
| void test_creation() { |
| expect(manager, isNotNull); |
| } |
| |
| Future test_removeFolder_multipleTokens() { |
| Folder folder = getFolder('/a/b'); |
| Token token1 = new Token('token1'); |
| Token token2 = new Token('token2'); |
| manager.addFolder(folder, token1); |
| manager.addFolder(folder, token2); |
| manager.removeFolder(folder, token2); |
| |
| File addedFile = newFile('/a/b/lib.dart'); |
| return _expectEvent(ChangeType.ADD, addedFile.path, [token1]); |
| } |
| |
| Future test_removeFolder_withChildren() async { |
| Folder topFolder = getFolder('/a/b'); |
| Folder childFolder = getFolder('/a/b/c/d'); |
| Token topToken = new Token('topToken'); |
| Token childToken = new Token('childToken'); |
| manager.addFolder(topFolder, topToken); |
| manager.addFolder(childFolder, childToken); |
| manager.removeFolder(topFolder, topToken); |
| |
| File addedFile = newFile('/a/b/c/d/lib.dart'); |
| await _expectEvent(ChangeType.ADD, addedFile.path, [childToken]); |
| |
| newFile('/a/b/lib.dart'); |
| return _expectNoEvent(); |
| } |
| |
| Future test_removeFolder_withNoChildren() { |
| Folder folder = getFolder('/a/b'); |
| Token token = new Token('token'); |
| manager.addFolder(folder, token); |
| manager.removeFolder(folder, token); |
| |
| newFile('/a/b/lib.dart'); |
| return _expectNoEvent(); |
| } |
| |
| Future _expectEvent(ChangeType expectedType, String expectedPath, |
| List<Token> expectedTokens) async { |
| await pumpEventQueue(); |
| WatchEvent event = listener.event; |
| expect(event, isNotNull); |
| expect(event.type, expectedType); |
| expect(event.path, expectedPath); |
| expect(listener.tokens, unorderedEquals(expectedTokens)); |
| listener.clear(); |
| } |
| |
| Future _expectNoEvent() async { |
| await pumpEventQueue(); |
| expect(listener.event, isNull); |
| expect(listener.tokens, isNull); |
| } |
| } |
| |
| @reflectiveTest |
| class WatchNodeTest extends Object with ResourceProviderMixin { |
| void test_creation_folder() { |
| Folder folder = getFolder('/a/b'); |
| WatchNode node = new WatchNode(folder); |
| expect(node, isNotNull); |
| expect(node.children, isEmpty); |
| expect(node.folder, folder); |
| expect(node.parent, isNull); |
| expect(node.subscription, isNull); |
| expect(node.tokens, isEmpty); |
| } |
| |
| void test_creation_noFolder() { |
| WatchNode node = new WatchNode(null); |
| expect(node, isNotNull); |
| expect(node.children, isEmpty); |
| expect(node.folder, isNull); |
| expect(node.parent, isNull); |
| expect(node.subscription, isNull); |
| expect(node.tokens, isEmpty); |
| } |
| |
| void test_delete_nested_child() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| WatchNode childNode = new WatchNode(getFolder('/a/b/c/d')); |
| WatchNode grandchildNode = new WatchNode(getFolder('/a/b/c/d/e')); |
| rootNode.insert(topNode); |
| rootNode.insert(childNode); |
| rootNode.insert(grandchildNode); |
| |
| childNode.delete(); |
| expect(rootNode.children, equals([topNode])); |
| expect(topNode.children, equals([grandchildNode])); |
| expect(topNode.parent, rootNode); |
| expect(grandchildNode.parent, topNode); |
| } |
| |
| void test_delete_nested_noChild() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| WatchNode childNode = new WatchNode(getFolder('/a/b/c/d')); |
| rootNode.insert(topNode); |
| rootNode.insert(childNode); |
| |
| childNode.delete(); |
| expect(rootNode.children, equals([topNode])); |
| expect(topNode.children, isEmpty); |
| expect(topNode.parent, rootNode); |
| } |
| |
| void test_delete_top_child() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| WatchNode childNode = new WatchNode(getFolder('/a/b/c/d')); |
| rootNode.insert(topNode); |
| rootNode.insert(childNode); |
| |
| topNode.delete(); |
| expect(rootNode.children, equals([childNode])); |
| expect(childNode.parent, rootNode); |
| } |
| |
| void test_delete_top_noChild() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| rootNode.insert(topNode); |
| |
| topNode.delete(); |
| expect(rootNode.children, isEmpty); |
| } |
| |
| void test_findParent_childOfLeaf() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| rootNode.insert(topNode); |
| |
| expect(rootNode.findParent('/a/b/c'), topNode); |
| } |
| |
| void test_findParent_childOfNonLeaf() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| WatchNode childNode = new WatchNode(getFolder('/a/b/c/d')); |
| rootNode.insert(topNode); |
| rootNode.insert(childNode); |
| |
| expect(rootNode.findParent('/a/b/c'), topNode); |
| } |
| |
| void test_findParent_noMatch() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| rootNode.insert(topNode); |
| |
| expect(rootNode.findParent('/c/d'), rootNode); |
| } |
| |
| void test_insert_intermediate_afterParentAndChild() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| WatchNode childNode = new WatchNode(getFolder('/a/b/c/d')); |
| WatchNode intermediateNode = new WatchNode(getFolder('/a/b/c')); |
| |
| rootNode.insert(topNode); |
| rootNode.insert(childNode); |
| rootNode.insert(intermediateNode); |
| expect(topNode.parent, rootNode); |
| expect(topNode.children, equals([intermediateNode])); |
| expect(intermediateNode.parent, topNode); |
| expect(intermediateNode.children, equals([childNode])); |
| expect(childNode.parent, intermediateNode); |
| expect(childNode.children, isEmpty); |
| } |
| |
| void test_insert_nested_afterParent() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| WatchNode childNode = new WatchNode(getFolder('/a/b/c/d')); |
| |
| rootNode.insert(topNode); |
| rootNode.insert(childNode); |
| expect(childNode.parent, topNode); |
| expect(childNode.children, isEmpty); |
| expect(topNode.children, equals([childNode])); |
| } |
| |
| void test_insert_nested_beforeParent() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| WatchNode childNode = new WatchNode(getFolder('/a/b/c/d')); |
| |
| rootNode.insert(childNode); |
| rootNode.insert(topNode); |
| expect(childNode.parent, topNode); |
| expect(childNode.children, isEmpty); |
| expect(topNode.children, equals([childNode])); |
| } |
| |
| void test_insert_top() { |
| WatchNode rootNode = new WatchNode(null); |
| WatchNode topNode = new WatchNode(getFolder('/a/b')); |
| |
| rootNode.insert(topNode); |
| expect(rootNode.children, equals([topNode])); |
| expect(topNode.parent, rootNode); |
| expect(topNode.children, isEmpty); |
| } |
| } |