// // Copyright 2014 Perforce Software Inc. // using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Perforce.Helper; using Perforce.P4; using System.IO; using System.Collections.Generic; using System.Threading; using System.Diagnostics; using Perforce; namespace Perforce_test { [TestClass] public class PerforceHelperTest { // Note that this test requires a local server to be setup - somewhat loosely based on // the SampleDepot for testing. // // Run the server using testdata\install.bat - which copies stuff over to testroot and then // runs server.bat in that directory. private static string serverUri = "localhost:1999"; private static string username = "bruno"; private static string password = "Brunopass"; private static string badPassword = "asdfsadfaf"; private static string dirPath = "//depot"; private static string filesPath = "//depot/Jam/MAIN/src"; private static string viewDepotPath = "//depot/Jam/MAIN/..."; private static string editFileDepotPath = "//depot/Jam/MAIN/src/command.c"; private static string graphicFileDepotPath = "//depot/www/dev/images/jamgraph-jam.gif"; private static string fileHistoryDepotPath = "//depot/Jam/REL2.1/src/headers.c"; private static string clientName = "TEST_P4API.NET_CLIENT"; private static string clientDescription = "Client created for test harness"; private static string clientRoot = @"c:\temp\TEST_P4API.NET_CLIENT"; private static string clientFileBase = clientRoot + @"\depot\Jam\MAIN\src\"; private static string editFileClientPath = clientFileBase + "command.c"; private PerforceHelper _p4; public TestContext TestContext { get; set; } [TestInitialize] public void Setup() { Log.Info("### Setup()"); _p4 = new PerforceHelper(serverUri, username); if (TestContext.Properties.Contains("init")) { var initValue = (string) TestContext.Properties["init"]; if (!Directory.Exists(clientRoot)) { Directory.CreateDirectory(clientRoot); } if (initValue.Contains("login")) { Log.Info("--- setup: logging in"); _p4.Login(password); } if (initValue.Contains("client")) { Log.Info("--- setup: creating client"); var client = _p4.CreateClient(clientName, clientRoot, clientDescription); } if (initValue.Contains("mapping")) { Log.Info("--- setup: creating client mapping"); _p4.ClientFolderMappingAdd(viewDepotPath); } } Log.Info("### TEST: " + TestContext.TestName); } [TestMethod] public void T001_ConnectionTest() { Log.Info("--- trying to connect"); Assert.IsTrue(_p4.Connect()); Log.Info("--- checking connection"); Assert.IsTrue(_p4.IsConnected()); } [TestMethod] public void T002_ServerTimeTest() { var currentTime = Utility.GetEpochTime(); Log.Info(string.Format("EPOCH TIME: {0}", currentTime)); var datetime = _p4.GetServerTime(); Log.Info(string.Format("{0}", datetime)); } [TestMethod] public void T004_LoginTest() { Log.Info("--- logging out to begin test"); _p4.Logout(); try { _p4.SetPassword("", password); } catch (Exception) { } Log.Info("--- checking with bad password"); Assert.IsFalse(_p4.Login(badPassword).Item1); //Assert.IsFalse(_p4.IsLoggedIn()); Log.Info("--- checking with valid password"); Assert.IsTrue(_p4.Login(password).Item1); Assert.IsTrue(_p4.IsLoggedIn()); } [TestMethod] public void T005_MapTest() { P4Server pserver = null; try { pserver = new P4Server(_p4.ServerURI, username, "", ""); } catch (Exception) { } P4MapApi target1 = new P4MapApi(pserver); String lr = "//ws/directory/..."; P4MapApi.Type type1 = P4MapApi.Type.Include; target1.Insert(lr, type1); int tCount1 = target1.Count; Assert.AreEqual(1, tCount1); P4MapApi target2 = new P4MapApi(pserver); String left2 = "//ws/..."; String right2 = "//depot/..."; P4MapApi.Type type2 = P4MapApi.Type.Include; target2.Insert(left2, right2, type2); int tCount2 = target2.Count; Assert.AreEqual(1, tCount2); P4MapApi actual = P4MapApi.Join(target1, target2); int tCount3 = actual.Count; Assert.AreEqual(1, tCount3); string translated = actual.Translate("//ws/directory/foo.txt", P4MapApi.Direction.LeftRight); Assert.AreEqual(translated, "//depot/directory/foo.txt"); P4MapApi map = new P4MapApi(pserver); map.Insert("//depot/some/dir/...", "//ws/another/dir/...", P4MapApi.Type.Include); var path = map.Translate("//depot/some/dir/fred.txt", P4MapApi.Direction.LeftRight); Assert.AreEqual("//ws/another/dir/fred.txt", path); path = map.Translate("//depot/some/dir/subdir/...", P4MapApi.Direction.LeftRight); Assert.AreEqual("//ws/another/dir/subdir/...", path); } [TestMethod] [TestProperty("init", "login")] public void T006_GetKeyTest() { var key = "p4search.url"; var result = _p4.GetKey(key); Log.Info(string.Format("{0} = {1}", key, result)); } [TestMethod] [TestProperty("init", "login")] public void T100_ListDepotsTest() { Log.Info("--- getting list of local depots"); var depots = _p4.ListDepots(true); Assert.IsNotNull(depots); foreach (var d in depots) { Log.Info(d.Id); } Assert.AreEqual(3, depots.Count); } [TestMethod] [TestProperty("init", "login")] public void T101_ListDirectoriesTest() { Log.Info(string.Format("--- getting list of directories in {0}", dirPath)); var dirs = _p4.ListDirectories(dirPath); foreach (var d in dirs) { Log.Info(d); } Log.Info("dirPath = " + dirPath); Assert.AreEqual(6, dirs.Count); } [TestMethod] [TestProperty("init", "login")] public void T102_ListFilesTest() { var fmdList = _p4.ListFiles(filesPath + "/*"); Log.Info("--- listing files on path"); foreach (var md in fmdList) { Log.Info(md.GetFileName()); } Assert.IsTrue(fmdList.Count > 70); } [TestMethod] [TestProperty("init", "login")] public void T103_ListClientsTest() { var clientList = _p4.ListClients(); Log.Info(string.Format("--- listing all clients owned by {0}", username)); foreach (var c in clientList) { Log.Info(c.Name); } Assert.AreEqual(6, clientList.Count); } [TestMethod] [TestProperty("init", "login")] public void T104_CreateClientTest() { Log.Info(string.Format("--- creating a client {0}", clientName)); var client = _p4.CreateClient(clientName, clientRoot, clientDescription); Assert.IsTrue(_p4.ClientExists(clientName)); var clientList = _p4.ListClients(); Assert.AreEqual(7, clientList.Count); } [TestMethod] [TestProperty("init", "login,client")] public void T105_ManageClientTest() { var client = _p4.ClientFolderMappingAdd(viewDepotPath); var entry = _p4.CreateMapEntry(viewDepotPath, client.Name, MapType.Include); Assert.IsTrue(client.ViewMap.Contains(entry)); Assert.IsTrue(_p4.ClientFolderMappingContains(viewDepotPath)); if (!_p4.IsServerCaseSensitive()) { Assert.IsTrue(_p4.ClientFolderMappingContains(viewDepotPath.ToLower())); } client = _p4.ClientFolderMappingRemove(viewDepotPath); if (client != null && client.ViewMap != null) { entry = _p4.CreateMapEntry(viewDepotPath, client.Name, MapType.Include); Assert.IsFalse(client.ViewMap.Contains(entry)); } } [TestMethod] [TestProperty("init", "login,client")] public void T110_ChangelistTests() { Log.Info("--- creating a new changelist"); var change = _p4.CreateChangelist("a test changelist"); Log.Info(string.Format("--- checking to see if changelist {0} is pending", change.Id)); Assert.IsTrue(change.Pending); Log.Info("--- retrieving the changelist from Perforce"); var change2 = _p4.GetChangelist(change.Id); Assert.AreEqual(change2.Id, change.Id); Assert.AreEqual("a test changelist", change.Description); Log.Info("--- deleting the pending changelist"); _p4.DeleteChangelist(change.Id); // Pending changes change = _p4.CreateChangelist("a test pending changelist"); Log.Info("--- trying to get the current pending changelist"); change2 = _p4.GetCurrentPendingChangelist(); Log.Info("--- testing to verify that changelist was retrieved"); Assert.IsNotNull(change2); Log.Info(string.Format("Current pending changelist is {0}", change2.Id)); // List all changes on the path var changes = _p4.ListChanges(filesPath); foreach (var c in changes) { Log.Info(string.Format("--- {0}", c.Id)); } Assert.AreEqual(50, changes.Count); var c1 = _p4.CreateChangelist("test change1"); var c2 = _p4.CreateChangelist("test change2"); var changelists = _p4.GetAllPendingChangelists(); Assert.AreEqual(3, changelists.Count); _p4.DeleteChangelist(c1); _p4.DeleteChangelist(c2); } [TestMethod] [TestProperty("init", "login,client")] public void T200_SyncWorkspaceFilesTest() { var files = _p4.RunSync("//...", syncArgs: new List<string>() {"-f"}); if (files != null) { Log.Info("--- sync results:"); foreach (var f in files) { Log.Info(string.Format("{0}", f.DepotPath)); } } else { Log.Info("--- no files need synchronization"); } } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T201_RunFstatTest() { var paths = new List<string>(); paths.Add(editFileDepotPath); paths.Add(editFileClientPath); var results = _p4.RunFstat(paths); foreach (var md in results) { Log.Info(md.DepotPath.Path); } Log.Info("-- testing metadata for new file"); var f = createRandomFile(clientFileBase); var md2 = _p4.RunFstat(f); Assert.IsNull(md2); _p4.MarkFileForAdd(f); md2 = _p4.RunFstat(f); Assert.IsNotNull(md2); Log.Info(md2.DepotPath.Path); f = createRandomFile(clientFileBase, withSpecialChars: true); md2 = _p4.RunFstat(f); Assert.IsNull(md2); _p4.MarkFileForAdd(f); md2 = _p4.RunFstat(f); Assert.IsNotNull(md2); Log.Info(md2.DepotPath.Path); var change = _p4.GetCurrentPendingChangelist(); _p4.RevertChangelist(change); _p4.DeleteChangelist(change); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T203_GetFilesModifiedSinceTest() { var serverTime = _p4.GetServerTime(); Log.Info(string.Format("SERVER TIME: {0}", serverTime)); var files = _p4.ListFiles("//...", showDeleted: true, sinceTime: serverTime); Assert.IsNull(files); var f = createRandomFile(clientFileBase); _p4.MarkFileForAdd(f); _p4.SubmitChangelist(); files = _p4.ListFiles("//...", showDeleted: true, sinceTime: serverTime); Assert.AreEqual(null, files); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T204_MoveFilesToNewChangelistTest() { _p4.RevertFiles(serverOnly: false, paths: "//..."); InitWorkspaceWatcher(); _p4.RunSync("//..."); var editList = _p4.CheckoutFiles(false, filesPath + "/..."); var count = editList.Count; var currentChange = _p4.GetCurrentPendingChangelist(); Log.Info(string.Format("--- current changelist has {0} files", currentChange.Files.Count)); Assert.AreEqual(count, currentChange.Files.Count); var newChange = _p4.CreateChangelist("a TEST changelist"); Assert.AreEqual(0, newChange.Files.Count); var files = new List<string>(); files.Add(editFileDepotPath); Log.Info(string.Format("--- moving files to changelist {0}", newChange.Id)); _p4.MoveFilesToNewChangelist(files, newChange.Id); currentChange = _p4.GetChangelist(currentChange.Id); Log.Info(string.Format("--- changelist now has {0} files", currentChange.Files.Count)); Assert.AreEqual(count - 1, currentChange.Files.Count); newChange = _p4.GetChangelist(newChange.Id); Assert.AreEqual(1, newChange.Files.Count); _p4.GatherOpenFilesInCurrentChangelist(); // CLEAN UP _p4.RevertChangelist(currentChange); _p4.DeleteChangelist(currentChange); _p4.RevertChangelist(newChange); _p4.DeleteChangelist(newChange); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T210_AddEditFileTest() { var fname1 = createRandomFile(clientFileBase); _p4.MarkFileForAdd(fname1); var list = _p4.GetChangelistFiles(); foreach (var item in list) { Log.Info(item.DepotPath.Path); } _p4.SubmitChangelist(); var fname2 = createRandomFile(clientFileBase, withSpecialChars: true); _p4.MarkFileForAdd(fname2); list = _p4.GetChangelistFiles(); foreach (var item in list) { Log.Info(item.DepotPath.Path); } _p4.SubmitChangelist(); // Now we edit files var files = _p4.CheckoutFiles(false, new string[] { fname1, fname2 }); Assert.AreEqual(2, files.Count); foreach (var f in files) { Log.Info(string.Format("{0}", f)); appendTextToFile(f.LocalPath.Path); } _p4.SubmitChangelist(); var changes = _p4.ListChanges(fname2); foreach (var c in changes) { Log.Info(string.Format("--- {0}", c.Id)); } Assert.AreEqual(2, changes.Count); // Now we edit files, move to new changelist and submit files = _p4.CheckoutFiles(false, new string[] { fname1, fname2 }); Assert.AreEqual(2, files.Count); foreach (var f in files) { Log.Info(string.Format("{0}", f)); appendTextToFile(f.LocalPath.Path); } var currentChange = _p4.GetCurrentPendingChangelist(); var newChange = _p4.CreateChangelist("another TEST changelist"); Assert.AreEqual(0, newChange.Files.Count); var editFiles = new List<string>(); editFiles.Add(fname1); editFiles.Add(fname2); Log.Info(string.Format("--- moving files to changelist {0}", newChange.Id)); _p4.MoveFilesToNewChangelist(editFiles, newChange.Id); currentChange = _p4.GetChangelist(currentChange.Id); Log.Info(string.Format("--- changelist now has {0} files", currentChange.Files.Count)); Assert.AreEqual(0, currentChange.Files.Count); newChange = _p4.GetChangelist(newChange.Id); Assert.AreEqual(2, newChange.Files.Count); // _p4.GatherOpenFilesInCurrentChangelist(); _p4.SubmitChangelist(newChange); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T220_ListDirectoriesTest() { Log.Info(string.Format("--- getting list of directories in {0}", dirPath)); var dirname1 = createRandomDir(clientFileBase); var dirname2 = createRandomDir(clientFileBase, withSpecialChars: true); Log.Info(string.Format("Creating dirs: {0}, {1}", dirname1, dirname2)); var fname1 = createRandomFile(dirname1); var fname2 = createRandomFile(dirname2, withSpecialChars: true); Log.Info(string.Format("Creating files: {0}, {1}", fname1, fname2)); _p4.MarkFileForAdd(fname1, fname2); var list = _p4.GetChangelistFiles(); foreach (var item in list) { Log.Info(item.DepotPath.Path); } _p4.SubmitChangelist(); var newDirs = new List<string>() { getDepotDirPath(dirname1, unescape: true), getDepotDirPath(dirname2, unescape: true) }; Log.Info(string.Format("New dirs: {0}", string.Join(", ", newDirs))); var dirs = _p4.ListDirectories(clientFileBase.Substring(0, clientFileBase.Length - 1)); var dirList = new List<string>(); foreach (var d in dirs) { Log.Info(d); dirList.Add(d); } foreach (var d in newDirs) { Assert.IsTrue(dirList.Contains(d)); } dirs = _p4.ListDirectories(filesPath); dirList = new List<string>(); foreach (var d in dirs) { Log.Info(d); dirList.Add(d); } foreach (var d in newDirs) { Assert.IsTrue(dirList.Contains(d)); } } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T222_DeleteFilesTest() { var f1 = createRandomFile(clientFileBase); var f2 = createRandomFile(clientFileBase, withSpecialChars: true); var d1 = getDepotPath(f1); var d2 = getDepotPath(f2); Log.Info(string.Format("-- Created file: {0}", f1)); Log.Info(string.Format("-- Created file: {0}", f2)); _p4.MarkFileForAdd(f1); _p4.MarkFileForAdd(f2); _p4.SubmitChangelist(); Log.Info("-- Preparing to delete"); var results = _p4.DeleteFiles(serverOnly: false, paths: f1); Assert.AreEqual(1, results.Count); Assert.AreEqual(d1, results[0].DepotPath.Path); foreach (var r in results) { Log.Info(string.Format("-- result: {0}", r.DepotPath.Path)); } results = _p4.DeleteFiles(serverOnly: false, paths: f2); Assert.AreEqual(1, results.Count); Assert.AreEqual(d2, results[0].DepotPath.Path); foreach (var r in results) { Log.Info(string.Format("-- result: {0}", r.DepotPath.Path)); } _p4.SubmitChangelist(); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T224_RenameFileTest() { var fname1 = createRandomFile(clientFileBase); var fname2 = createRandomFile(clientFileBase, withSpecialChars: true); Log.Info(string.Format("-- Source file: {0}", fname1)); Log.Info(string.Format("-- Source file: {0}", fname2)); _p4.MarkFileForAdd(fname1); _p4.MarkFileForAdd(fname2); _p4.SubmitChangelist(); Log.Info(string.Format("-- added {0} to server", fname1)); Log.Info(string.Format("-- added {0} to server", fname2)); var fprime1 = getRandomFileName(clientFileBase); var fprime2 = getRandomFileName(clientFileBase, withSpecialChars: true); Log.Info(string.Format("-- Destination file: {0}", fprime1)); Log.Info(string.Format("-- Destination file: {0}", fprime2)); var results = _p4.RenameFile(fname1, fprime1); Assert.AreEqual(getDepotPath(fprime1), results[0].DepotPath.Path); foreach (var r in results) { Log.Info(string.Format("-- result: {0}", r.DepotPath.Path)); } results = _p4.RenameFile(fname2, fprime2); Assert.AreEqual(getDepotPath(fprime2), results[0].DepotPath.Path); foreach (var r in results) { Log.Info(string.Format("-- result: {0}", r.DepotPath.Path)); } var submitResults = _p4.SubmitChangelist(); Log.Info(string.Format("-- submitted changelist @{0}", submitResults.Results.ChangeIdAfterSubmit)); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T225_CopyFileTest() { var src1 = createRandomFile(clientFileBase); var src2 = createRandomFile(clientFileBase, withSpecialChars: true); Log.Info(string.Format("-- Source file: {0}", src1)); Log.Info(string.Format("-- Source file: {0}", src2)); _p4.MarkFileForAdd(src1); _p4.MarkFileForAdd(src2); _p4.SubmitChangelist(); var targ1 = getRandomFileName(clientFileBase); var targ2 = getRandomFileName(clientFileBase, withSpecialChars: true); _p4.CopyFile(src1, targ1); _p4.CopyFile(src2, targ2); var submitResults = _p4.SubmitChangelist(); Log.Info(string.Format("-- submitted changelist @{0}", submitResults.Results.ChangeIdAfterSubmit)); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T226_GetFileHistoryTest() { var history = _p4.GetFileHistory(fileHistoryDepotPath); Assert.AreEqual(4, history.Count); foreach (var h in history) { Log.Info(string.Format("DepotPath: {0}", h.DepotPath.Path)); Log.Info(string.Format("Revision: {0}", h.Revision)); Log.Info(string.Format("Modified by: {0}", h.UserName)); Log.Info(string.Format("Description: {0}", h.Description)); Log.Info(string.Format("Checked in: {0}", h.Date)); } var f1 = createRandomFile(clientFileBase); var f2 = createRandomFile(clientFileBase, withSpecialChars: true); Log.Info(string.Format("-- Source file: {0}", f1)); Log.Info(string.Format("-- Source file: {0}", f2)); _p4.MarkFileForAdd(f1); _p4.MarkFileForAdd(f2); _p4.SubmitChangelist(); history = _p4.GetFileHistory(f1); Assert.AreEqual(1, history.Count); Assert.AreEqual(history[0].DepotPath.Path, getDepotPath(f1)); history = _p4.GetFileHistory(f2); Assert.AreEqual(1, history.Count); Assert.AreEqual(history[0].DepotPath.Path, getDepotPath(f2)); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T227_ShelveFileTest() { var f1 = createRandomFile(clientFileBase); var f2 = createRandomFile(clientFileBase, withSpecialChars: true); var d1 = getDepotPath(f1); var d2 = getDepotPath(f2); Log.Info(string.Format("-- Source files: {0}, {1}", f1, f2)); var specs = _p4.MarkFileForAdd(new [] {f1, f2}); Assert.AreEqual(2, specs.Count); _p4.SubmitChangelist(); var files = _p4.CheckoutFiles(false, new string[] { f1, f2 }); Assert.AreEqual(2, files.Count); foreach (var f in files) { Log.Info(string.Format("{0}", f)); appendTextToFile(f.LocalPath.Path); } _p4.ShelveFiles(new [] {f1, f2}); Assert.IsTrue(_p4.IsFileShelved(d1)); Assert.IsTrue(_p4.IsFileShelved(d2)); var shelved = _p4.GetShelvedChangelistFiles(); Assert.AreEqual(2, shelved.Count); var paths = new List<string>() { d1, d2 }; Assert.IsTrue(paths.Contains(shelved[0].Path.Path)); Assert.IsTrue(paths.Contains(shelved[1].Path.Path)); foreach (var s in shelved) { Log.Info(string.Format("-- {0}", s.Path.Path)); } // Revert opened files _p4.RevertFiles(serverOnly: false, paths: "//..."); var unshelved = _p4.UnshelveFiles(); Assert.AreEqual(2, unshelved.Count); var result = _p4.RunCmd("opened", false, new string[] { }); Assert.AreEqual(2, result.InfoOutput.Count); RemoveShelvedChanges(); } public void RemoveShelvedChanges() { var results = _p4.DeleteShelvedFiles(paths: "//..."); var shelved = _p4.GetShelvedChangelistFiles(); Assert.IsNull(shelved); _p4.RevertFiles(serverOnly: true, paths: "//..."); _p4.DeletePendingChangeList(); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T228_ReconcileFileTest() { var f1 = createRandomFile(clientFileBase); var f2 = createRandomFile(clientFileBase, withSpecialChars: true); var d1 = getDepotPath(f1); var d2 = getDepotPath(f2); var result = _p4.ReconcileFiles(new [] {f1, f2}); Log.Info(string.Format("{0}", result)); var md = _p4.RunFstat(f1); Assert.AreEqual(f1, md.ClientPath.Path); Assert.AreEqual(d1, md.DepotPath.Path); md = _p4.RunFstat(f2); Assert.AreEqual(f2, md.ClientPath.Path); Assert.AreEqual(d2, md.DepotPath.Path); _p4.SubmitChangelist(); System.IO.File.SetAttributes(f1, FileAttributes.Normal); System.IO.File.SetAttributes(f2, FileAttributes.Normal); System.IO.File.Delete(f1); System.IO.File.Delete(f2); result = _p4.ReconcileFiles(new [] { f1, f2 }); Log.Info(string.Format("{0}", result)); Assert.AreEqual(2, result.TaggedOutput.Count); md = _p4.RunFstat(f1); Assert.AreEqual(f1, md.ClientPath.Path); Assert.AreEqual(d1, md.DepotPath.Path); md = _p4.RunFstat(f2); Assert.AreEqual(f2, md.ClientPath.Path); Assert.AreEqual(d2, md.DepotPath.Path); } [TestMethod] [TestProperty("init", "login")] public void T230_GetFileFromServerTest() { var filename = _p4.GetFileFromServer(graphicFileDepotPath); Log.Info(filename); } [TestMethod] [TestProperty("init", "login")] public void T231_GetDirectoryFromServerTest() { var dir = @"c:\temp\junk"; Directory.CreateDirectory(dir); var results = _p4.GetDirectoryFromServer(filesPath, dir); Log.Info(results); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T232_GetFileFromShelfTest() { var f = createRandomFile(clientFileBase); Log.Info(string.Format("-- Source file: {0}", f)); var specs = _p4.MarkFileForAdd(f); var depotPath = specs[0].DepotPath.Path; Log.Info(string.Format("-- Depot path: {0}", depotPath)); var shelvedFiles = _p4.ShelveFiles(f); Assert.IsTrue(_p4.IsFileShelved(depotPath)); var change = _p4.GetOrCreatePendingChangelist(); Log.Info(string.Format("-- Change id: {0}", change.Id)); _p4.RevertFiles(serverOnly: false, paths: f); var downloaded = _p4.GetFileFromShelf(depotPath); } [TestMethod] [TestProperty("init", "login,client")] public void T235_GetPathSizesTest() { var sizes = _p4.GetPathSizes(viewDepotPath); Log.Info(string.Format("{0} {1} files {2} kb", sizes.Path, sizes.FileCount, sizes.FileSize/1024)); } [TestMethod] [TestProperty("init", "login,client")] public void T240_IsDirectoryMappedTest() { var path = "//depot/MapTest"; _p4.ClientFolderMappingAdd(path + "/..."); var result = _p4.IsDirectoryMapped(path); Assert.IsTrue(result); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T250_RollbackFileToRevisionTest() { RemoveShelvedChanges(); var f1 = createRandomFile(clientFileBase); var f2 = createRandomFile(clientFileBase, withSpecialChars: true); var d1 = getDepotPath(f1); var d2 = getDepotPath(f2); Log.Info(string.Format("-- Source file: {0}", f1)); Log.Info(string.Format("-- Source file: {0}", f2)); var specs = _p4.MarkFileForAdd(new[] { f1, f2 }); Assert.AreEqual(2, specs.Count); _p4.SubmitChangelist(); var c1 = ReadContents(f1); var c2 = ReadContents(f2); var files = _p4.CheckoutFiles(false, new string[] { f1, f2 }); Assert.AreEqual(2, files.Count); foreach (var f in files) { Log.Info(string.Format("{0}", f)); appendTextToFile(f.LocalPath.Path); } _p4.SubmitChangelist(); _p4.RollbackFileToRevision(f1, 1); var md = _p4.RunFstat(f1); Assert.AreEqual(3, md.HeadRev); var ac1 = ReadContents(f1); Assert.AreEqual(c1, ac1); _p4.RollbackFileToRevision(f2, 1); md = _p4.RunFstat(f2); Assert.AreEqual(3, md.HeadRev); var ac2 = ReadContents(f2); Assert.AreEqual(c2, ac2); // Do another edit files = _p4.CheckoutFiles(false, new string[] { f1, f2 }); Assert.AreEqual(2, files.Count); foreach (var f in files) { Log.Info(string.Format("{0}", f)); appendTextToFile(f.LocalPath.Path); } _p4.SubmitChangelist(); _p4.RollbackFileToRevision(d1, 1); md = _p4.RunFstat(f1); Assert.AreEqual(5, md.HeadRev); ac1 = ReadContents(f1); Assert.AreEqual(c1, ac1); _p4.RollbackFileToRevision(d2, 1); md = _p4.RunFstat(f2); Assert.AreEqual(5, md.HeadRev); ac2 = ReadContents(f2); Assert.AreEqual(c2, ac2); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T251_RollbackFolderToChangelistTest() { InitWorkspaceWatcher(); _p4.RunSync("//..."); var path = "//depot/Jam/MAIN/src"; var changeId = 320; var results = _p4.RollbackFolderToChangelist(path, changeId); } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T260_SubmitFileTest() { var f1 = createRandomFile(clientFileBase); Log.Info(string.Format("-- Created file: {0}", f1)); var addResults = _p4.MarkFileForAdd(f1); Assert.AreEqual(addResults.Count, 1); var depotFile = addResults[0].DepotPath.Path; Log.Info(string.Format("-- depot file: {0}", depotFile)); var submitResults = _p4.SubmitSingleFile(depotFile, "TEST: SubmitFileTest()"); Log.Info(string.Format("-- change {0} submitted", submitResults.Results.ChangeIdAfterSubmit)); var f2 = createRandomFile(clientFileBase); Log.Info(string.Format("-- Created file: {0}", f2)); addResults = _p4.MarkFileForAdd(f2); Assert.AreEqual(addResults.Count, 1); depotFile = addResults[0].DepotPath.Path; Log.Info(string.Format("-- depot file: {0}", depotFile)); submitResults = _p4.SubmitSingleFile(depotFile, "TEST: SubmitFileTest()"); Log.Info(string.Format("-- change {0} submitted", submitResults.Results.ChangeIdAfterSubmit)); } private static WorkspaceWatcher.RefreshSelectorDelegate RefreshSelector() { Log.TraceFunction(); return null; } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T300_FileSystemWatcherTest() { int delay = 1500; string fileBase = clientRoot + @"\depot\Jam\REL2.1\tdir\"; string dirPath = "//depot/Jam/REL2.1/tdir/..."; _p4.ClientFolderMappingAdd(dirPath); WorkspaceWatcher.SetRefreshSelectorFuntion(RefreshSelector()); _p4.RevertFiles(true, new string[] {"//..."}); _p4.RunCmd("obliterate", false, new[] {"-y", dirPath}); var chg = _p4.CreateChangelist("Test watcher submit"); var watcher = InitWorkspaceWatcher(); var results = _p4.RunSync("//depot/Jam/MAIN/...#0"); results = _p4.RunSync("//depot/Jam/MAIN/..."); watcher.SyncMatcherReset(); watcher.Start(); var f1 = createRandomFile(fileBase); var f2 = createRandomFile(fileBase, withSpecialChars: true); var f3 = createRandomFile(fileBase); var f4 = createRandomFile(fileBase, withSpecialChars: true); Log.Info(string.Format("-- Created files: {0}, {1}, {2}, {3}", f1, f2, f3, f4)); // Allow FSWatcher to see and add the file Thread.Sleep(delay); var fstat1 = _p4.RunFstat(f1); var fstat2 = _p4.RunFstat(f2); var fstat3 = _p4.RunFstat(f3); var fstat4 = _p4.RunFstat(f4); Assert.AreEqual(FileAction.Add, fstat1.Action); Assert.AreEqual(FileAction.Add, fstat2.Action); Assert.AreEqual(FileAction.Add, fstat3.Action); Assert.AreEqual(FileAction.Add, fstat4.Action); _p4.SubmitChangelist(); // Edit file and let it notice change System.IO.File.SetAttributes(f1, System.IO.File.GetAttributes(f1) & ~FileAttributes.ReadOnly); System.IO.File.SetAttributes(f2, System.IO.File.GetAttributes(f2) & ~FileAttributes.ReadOnly); appendTextToFile(f1); appendTextToFile(f2); Thread.Sleep(delay); fstat1 = _p4.RunFstat(f1); fstat2 = _p4.RunFstat(f2); Assert.AreEqual(FileAction.Edit, fstat1.Action); Assert.AreEqual(FileAction.Edit, fstat2.Action); // Delete file and let it notice change System.IO.File.Delete(f1); System.IO.File.Delete(f2); Thread.Sleep(delay); fstat1 = _p4.RunFstat(f1); fstat2 = _p4.RunFstat(f2); Assert.AreEqual(FileAction.Delete, fstat1.Action); Assert.AreEqual(FileAction.Delete, fstat2.Action); // Rename files var f5 = f3 + "-new"; var f6 = f4 + "-new"; System.IO.File.Move(f3, f5); System.IO.File.Move(f4, f6); Thread.Sleep(delay); fstat3 = _p4.RunFstat(f3); fstat4 = _p4.RunFstat(f4); var fstat5 = _p4.RunFstat(f5); var fstat6 = _p4.RunFstat(f6); Assert.AreEqual(FileAction.MoveDelete, fstat3.Action); Assert.AreEqual(FileAction.MoveDelete, fstat4.Action); Assert.AreEqual(FileAction.MoveAdd, fstat5.Action); Assert.AreEqual(FileAction.MoveAdd, fstat6.Action); _p4.SubmitChangelist(); var result = _p4.RunCmd("revert", false, new string[] { "//..." }); watcher.Stop(); } private WorkspaceWatcher InitWorkspaceWatcher() { var watcher = new WorkspaceWatcher(); watcher.WatchInterval = 100; watcher.WatchPath = clientRoot; watcher.PerforceHelper = _p4; _p4.TestWorkspaceWatcher = watcher; return watcher; } [TestMethod] [TestProperty("init", "login,client,mapping")] public void T310_FileSystemWatcherTestSyncs() { int delay = 400; WorkspaceWatcher.SetRefreshSelectorFuntion(RefreshSelector()); _p4.RevertFiles(true, new[] { "//..." }); _p4.RunCmd("revert", false, new[] { "//..." }); _p4.RunCmd("sync", false, new[] { "//depot/Jam/MAIN/...#0" }); var watcher = new WorkspaceWatcher(); watcher.WatchInterval = 100; watcher.WatchPath = clientRoot; watcher.PerforceHelper = _p4; _p4.TestWorkspaceWatcher = watcher; watcher.SyncMatcherReset(); watcher.Start(); // Now we remove files and see what get's spotted var syncResult = _p4.RunSync("//depot/Jam/MAIN/src/jam..."); Thread.Sleep(delay * 20); var result = _p4.RunCmd("opened", false, new string[] { }); Assert.AreEqual(result.InfoOutput.Count, 0); watcher.Stop(); } [TestMethod] [TestProperty("init", "login,client")] public void T998_DeleteClientTest() { Log.Info("--- deleting pending and shelved changelist"); var results = _p4.DeleteShelvedFiles(paths: "//..."); _p4.RevertFiles(serverOnly: true, paths: "//..."); _p4.DeletePendingChangeList(); Log.Info(string.Format("--- removing the client {0}", clientName)); _p4.DeleteClient(clientName); Assert.IsFalse(_p4.ClientExists(clientName)); } [TestMethod] public void T999_LogoutTest() { Log.Info("--- logging out"); Assert.IsTrue(_p4.Logout()); Assert.IsFalse(_p4.IsLoggedIn()); } [TestCleanup] public void Teardown() { Log.Info("### Teardown()"); } private string ReadContents(string fileName) { using (FileStream stream = System.IO.File.OpenRead(fileName)) { using (var ms = new MemoryStream()) { stream.CopyTo(ms); return ms.ToString(); } } } // _p4 methods private string createRandomFile(string baseDir, bool withSpecialChars = false) { var fileName = getRandomFileName(baseDir, withSpecialChars); if (!Directory.Exists(baseDir)) Directory.CreateDirectory(baseDir); byte[] data = new byte[8192]; Random rng = new Random(); using (FileStream stream = System.IO.File.OpenWrite(fileName)) { for (int i = 0; i < 8; i++) { rng.NextBytes(data); stream.Write(data, 0, data.Length); } } return fileName; } private string createRandomDir(string baseDir, bool withSpecialChars = false) { var dirName = getRandomDirName(baseDir, withSpecialChars); if (!Directory.Exists(baseDir)) Directory.CreateDirectory(baseDir); if (!Directory.Exists(dirName)) Directory.CreateDirectory(dirName); return dirName; } private string getRandomFileName(string baseDir, bool withSpecialChars = false) { var rndName = Path.GetRandomFileName(); if (withSpecialChars) rndName = Path.GetFileNameWithoutExtension(rndName) + "#special" + Path.GetExtension(rndName); var fileName = Path.Combine(baseDir, rndName); return fileName; } private string getRandomDirName(string baseDir, bool withSpecialChars = false) { var rndName = Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); if (withSpecialChars) rndName += "#special"; return Path.Combine(baseDir, rndName); } private string getDepotPath(string fname, bool escape=true) { fname = Path.GetFileName(fname); if (escape) fname = PerforceHelper.EscapePath(fname); return string.Format("{0}/{1}", filesPath, fname); } private string getDepotDirPath(string dirname, bool unescape = true) { var dirroot = Path.GetDirectoryName(dirname); dirname = dirname.Substring(dirroot.Length + 1); // Skip over "\\" dirname = string.Format("{0}/{1}", filesPath, dirname); if (unescape) dirname = PerforceHelper.UnescapePath(dirname); return dirname; } private void appendTextToFile(string file) { var random = new Random(); var numlines = random.Next(10)+1; using (StreamWriter sw = System.IO.File.AppendText(file)) { for (var i = 0; i < numlines; i++) { sw.WriteLine(generateRandomString()); } } } private string generateRandomString() { var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var stringChars = new char[8]; var random = new Random(); for (int i = 0; i < stringChars.Length; i++) { stringChars[i] = chars[random.Next(chars.Length)]; } return new String(stringChars); } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 16817 | christoph_leithner | "Forking branch Main of perforce-software-piper to christoph_leithner-piper." | ||
//guest/perforce_software/piper/main/windows/R1.1/Perforce-test/PerforceHelperTest.cs | |||||
#1 | 16507 | perforce_software | Move to main branch. | ||
//guest/perforce_software/piper/windows/R1.1/Perforce-test/PerforceHelperTest.cs | |||||
#3 | 16474 | Robert Cowham | Bring up-to-date with //guest/perforce_software/piper/windows/main/...@16473 | ||
#2 | 13572 | alan_petersen | updating R1.1 | ||
#1 | 11256 | alan_petersen |
Populate //guest/perforce_software/piper/windows/R1.1/... from //guest/perforce_software/piper/windows/main/.... |
||
//guest/perforce_software/piper/windows/main/Perforce-test/PerforceHelperTest.cs | |||||
#1 | 11255 | alan_petersen | Rename/move file(s) | ||
//guest/perforce_software/piper/windows/Perforce-test/PerforceHelperTest.cs | |||||
#3 | 11032 | alan_petersen |
MEGA UPDATE: - fixed bug in folder rollback was failing due to deleted files - files needed to be re-added with the downgrade (-d) flag - put some checking in to stop/start the background workers when - folder versioning - can select 'show versions' on mapped folders - currently limites the number of changelists displayed to the last 50 - rollback button is disabled/hidden unless there are no files in the path (//path/to/folder/...) that are opened (uses p4 opened -a path) - various fixes for some strange null pointer exceptions - fixed folder items (edit all/revert all) - needs some testing to ensure that it is functioning correctly (e.g. when there are locked files in the path being checked out) - general code clean-up -- primarily using the Utility method to obtain the PerforceHelper, rather than having to cast all the time. - found some stability issues (at least when communicating with a local p4d running in the same virtual machine) so some additional error checking/handling was added - reconcile files action now provides feedback via a wait dialog: while reconcile is running, the dialog is displayed along with a wait indicator, when complete a message is displayed that the reconcile is finished - submit changes - submit now perfomed within a wait dialog: dialog displays message along with a wait indicator, results of the submit are displayed when complete - currently, the 'ok' button is disabled until the submit completes. - looking into providing a progress bar (using the feedback mechanism in the API) to provide some more interesting information (and to give users the sense that something is actually happening when a large changelist is begin submitted) - added copy function to PerforceHelper along with test case - implemented copy (ctrl-c) and paste (ctrl-v) in DESI - limitations: - currently only implemented for FILES (not folders) - to paste, one must select the destination FOLDER - next steps: - get working for folders - implement cut (ctrl-x) - permit paste into a column (more intuitive) - rebuilt using 'Any CPU' target -- not sure if this will fix the error seen by the Win7-64 user -- we may need to switch to separate 32- and 64-bit builds - fixed defect #78: delete and move/delete files are no longer displayed in the server view - fixed defect #76: tags now displayed in version history - added MemoryCache for repository reference -- the repository reference was getting stale and creating strange errors, so a reference is now stored in the MemoryCache with a SlidingExpiration of 2 minutes. - fixes #80: copy checks out file -- remnant of code from the rename logic was checking out the code - fixes #14: mail now opens outlook using office API - fixes #72: submit dialog now waits for results from submit, and if there is an error the error message is displayed, otherwise the changelist number is displayed - fixes #75: folder versioning changes -- restore version button now always displayed, but not connected to anything if the folder has opened items; -- opened items now ignored items marked for Add -- this could result in the folder being re-created if/when the user submits the added files - fixed bug in submit dialog in which changelist number was not displayed correctly - fixed bug in submission of partial changelists -- files moved to new changelist but original not updated, resulting in error - #79 - add file now works correctly, relying on the client path rather than the //dummy_depot_path #41: various changes and refactoring to support 'Recent' view - background sync causes immediate refresh of the recent list - ability to mark items as 'read' -- removed from the recent list and the view is refreshed #43 - udpates to logic to deal with transient threading issues (causing the NoSuchObject exceptions) and sync/refresh of workspace files to added files. #48: submit single file now working -- when submit file is selected, the file is moved to a shiny new changelist, and that changelist is presented in the UI - refactoring of submit pane logic to allow passing in a changelist ID incremental build with partially working toolbar buttons -- still working on the forward/back buttons (they aren't quite working right yet) - toolbar items are now functional: left/right nav, add files, create folder addresses #12: favorite folders -- added favorite folder functionality to the application - favorites are now stored in a workspace-specific property (client_name.favoriteFolders) in the favorites.json file in the user's configuration directory (this file is created if it does not exist) - favorites can be edited by double-clicking on the label, right-clicking the label and selecting 'edit', or clicking on the edit icon - favorites can be deleted by right-clicking on the label and selecting 'delete' update involved various refactoring so enable the hidden 'Favorites' selector and select the appropriate sidebar selector (Workspace or Server) when the favorite is selected - favorite tags implemented, satisfying ticket #18 - favorite tags are stored in a workspace-specific property (client_name.favoriteTags) in the favorites.json file in the user's configuration directory (this file is created if it does not exist) - favorite tags can be added by clicking on the '+' that appears when hovering over the Favorite Tags header in the sidebar - a popup appears with a textfield - ESC cancels the add and closes the popup - Enter or clicking on the add button adds the tag to the property (immediately saved) and updates the Favorite Tags sidebar list and closes the popup - changing focus (ie clicking somewhere else in the application) cancels the add and closes the popup - favorite tags can be selected/deselected with a single click - selected tags have a checkmark in the rightmost column - favorite tags can be deleted by right-clicking on the label and selecting 'delete' - list items in ColumnDisplay.xaml modified - FileItem model class modified with boolean method to determine if the file has a selected tag (matching is case insensitive) - FavoritesHelper caches selected tags (to avoid unnecessary IO and parsing) - FavoriteTagItem modified to - fixing copy/paste functionality: - copy/paste now uses filesystem copy and paste (rather than p4 copy) - CopyDirectory method added to Utility class to assist in copying of entire directory structures - copy enabled from either the server tab or the workspace tab... paste only allowed on the workspace tab - wait dialog implemented for the paste process -- should happen quickly if copy is on local filesystem, but if copy is from the server then copy may take a while if the file(s) being copied are large (they have to be downloaded first) - confirmation dialog when folders selected for the copy (giving user the option of skipping large directories if they were selected accidentally) - implementation of p4 sizes code to determine size/number of files in a given path - implementation of p4 print for a depot path -- by default saves to a temp directory, but in the case of copy/paste the print is performed directly to the target directory Addresses DEFECT #91 -- Desi crashing on viewing old versions - previous refactoring had introduced the VersionItem model class, but there were still some remnants of references to FileHistory around, causing issues (ie. crashing) - changelist cleanup had used the -f (force) flag, which hadn't appeared as an issue because the test cases currently run as an admin user, but that masked the fact that only admins can do 'p4 change -d -f'. Doh #94 DEFECT: Selecting tags causes error in Server view - issue was due to tag attributes not retrieved in HEX format, so hex decoding then failed (because they weren't hex!) - this is now fixed in the PerforceHelper - general code cleanup and optimization - helper methods in the utility class to retrieve common objects from the App context - start sync now first checks the preferences to ensure that sync is actually turned on - background processes now wait for initial workspace selection before starting up #36: DEFECT: Refresh color coding - modifications for #88 fix this too #52: DEFECT: Cannot move files from "My Pending Changes" to "Trash" - modified CommandHelper logic to revert files that are in any state other than 'None' when trying to delete #88: DEFECT: icon should be different for items not on server - logic to determine file status updated - icon sizes bumped up slightly (from 18px to 24px) to make differences more visible.. #96: DEFECT: Adding files double window - this was due to a bug in the AddFilesButton_Click method of ToolBar.xaml.cs... basically ShowDialog() was called twice! DOH!! #99: DEFECT: Refresh color coding - modified logic around refreshing after a paste, seems to have fixed this issue #106: DEFECT: Paste a file in a folder where the name exists and the application crashes - added CopyFileToDirectory method to utility class to check to see if the destination file already exists... if it does, then (Copy) is appended to the filename - if there is already a file named xxx (Copy), then a counter is appended: xxx (Copy 2) - this is repeated until it comes up with a filename that doesn't conflict #104: DEFECT: right click option to open file as read only does not work - Code in ContextMenuHelper's ViewWorkspaceFile method was not wired to the code that opens a file. Now it is! - no specific bugs fixed, just trying to get refresh to be a little more responsive and context menus working a little better - reworked DelegateCommand to permit parameter - reworked various menuitem commands to include item(s) selected as parameters - reworked command methods to get parameter, cast it appropriately to the item(s), perform the operation(s), and then refresh the items as well as associated UI components - reworked some methods in MainWindow to take item(s) as arguments (rather than just trying to get the currently selected item -- sometimes when you right-click on something it isn't fully selected) #107: Defect: Unsync from computer not working - modified code that syncs/unsyncs to refresh items after change -- should make for a more responsive interface - modified PerforceHelper code that sets the client to ensure that rmdir is set as an option - fixed Exit menu item to actually shut down the application (YAY) #49: Defect: Desi throws exception when internet connection is lost - modified the GetPerforceHelper utility method to check for a live server. If the server is unreachable, the user is presented with the option to relaunch the application or shutdown #97: DEFECT: Object error when using navigation buttons - code was checking Perforce server to determine if a path was a directory or file, but when the file was newly created it doesn't exist on the server so it returned false, which later caused a null pointer exception. The PerforceHelper IsDirectory code was modified to check, as a last restort, the client path to see if the file is a directory using System.IO.Directory.exists() - modification to MainWindow.cs to re-enable the filesystem watcher #73: Defect: Checkout and delete file .. appropriate change in status not done - code in filesystem watcher was not handing deletes of opened files correctly... opened files need to be reverted first, then they can be deleted using a p4 delete. Since the file no longer exists on the filesystem, these p4 commands are performed as server-only (-k option). When the file is an Add or MoveAdd, then the server-side revert is just performed. Otherwise, if the file is in any other state (other than none), a server-side revert is performed, then the server-side delete. #92: Defect: Option for unshelving missing - added a button to the file info screen for unshelving. Since unshelving may overwrite changes the user has made, a dialog is presented and the user must confirm the unshelve operation. - application now opens with window displaying the file/folder in question when given a command-line argument in the form p4://... |
||
#2 | 10804 | alan_petersen |
UPDATE: - some code cleanup - submit now catches errors more intelligently and displays them - connection failures in background processes now display dialog indicating connection failure - this stops the background process (this will avoid the endless dialog boxes seen in the Mac version!) - currently, dismissing the dialog exits the application -- this may change once I get the 'change connection' feature working |
||
#1 | 10761 | alan_petersen |
initial drop of Piper for Windows.... this version still has _many_ bugs (er... i mean "unintended features") but I will be updating it over the next week as more stability is added. |