/***************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
This code is licensed under the Visual Studio SDK license terms.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
***************************************************************************/
//*************************************************************************************************
// MyTestTip.cs
//
// This file defines the MyTest tip.
//
// Copyright(c) Microsoft Corporation, 2004
//*************************************************************************************************
namespace Microsoft.VisualStudio.TestTools.Samples
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.TestTools.Common;
using Microsoft.VisualStudio.TestTools.Exceptions;
using Microsoft.VisualStudio.TestTools.TestManagement;
using Microsoft.VisualStudio.TestTools.Vsip;
/// <summary>
/// MyTest ITip implementation.
/// The important methods to implement for your TIP are:
/// - TestType property get: return the test type defined in your
/// test element.
/// - Load: Load is called by TMI when a project containing your test
/// types is loaded. Load create instances of your ITestElement and
/// returns them to TMI.
///
/// A TIP can only throw certain exceptions up to TMI. Here's the current
/// list of valid exceptions out of Microsoft.VisualStudio.TestTools.Exceptions:
/// StorageNotAccessibleException
/// InvalidDataInStorageException
/// ErrorReadingStorageException
/// DuplicateIdException
/// IdNotFoundException
/// InvalidTestObjectException
/// SaveNotSupportedException
/// CreateNewTestNotSupportedException
/// WrongResultTypeException
/// CorruptedResultException
/// EqtDataException
///
/// </summary>
// Use RegisterTestTypeNoEditor (and CLSCompliant(false)
// to describe your TIP if you don't implement a package/TUIP.
// If you do implement a package/TUIP, use the RegisterTestType attribute
// on your package class. (For this sample, see MyTestPackage.)
// [CLSCompliant(false)]
// [RegisterTestTypeNoEditor(typeof(MyTest), typeof(MyTestTip), new string[] { ".mytest" }, new int[] { MyTestIconId }, MyTestNameId)]
internal sealed class MyTestTip : ITip
{
#region Constructors
// Suppress AvoidUnusedParameters.
// The ITmi parameter is required on the constructor; we just don't happen to use it here.
[SuppressMessage("Microsoft.Performance", "CA1801")]
public MyTestTip(ITmi tmi)
{ }
#endregion
#region ITip methods
/// <summary>
/// Returns TestType object for given TIP. There is 1:1 between TIPs and TestTypes
/// </summary>
/// <value>The Test Type that this TIP is for. This value is never null</value>
public TestType TestType
{
get { return MyTest.MyTestType; }
}
/// <summary>
/// Loads elements from specified location into memory
///
/// This method uses exceptions for error conditions -- Not return values.
/// </summary>
/// <param name="location">Location to load tests from.</param>
/// <param name="projectData">Project information object.</param>
/// <param name="warningHandler">Warning handler that processes warnings.</param>
/// <returns>The data that has been loaded</returns>
public ICollection Load(string location, ProjectData projectData, IWarningHandler warningHandler)
{
MyTestAssertHelper.StringNotNullOrEmpty(location, "location");
List<ITestElement> tests = new List<ITestElement>(); // Collection of tests loaded from disk
if (File.Exists(location))
{
using (StreamReader sr = File.OpenText(location))
{
while (sr.Peek() >= 0)
{
// Open the file and read the parameters for this test
string line = sr.ReadLine();
string[] fields = line.Split(','); // The delemeter in the file
if (fields.Length == 3 && fields[2].IndexOfAny(Path.GetInvalidPathChars()) == -1)
{
// We're ok, so set the properties and add to the test collection
MyTest test = new MyTest(fields[0], fields[1], fields[2]);
test.Storage = location;
test.ProjectData = projectData;
tests.Add(test);
}
}
}
}
else
{
throw new ErrorReadingStorageException();
}
return tests;
}
/// <summary>
/// Saves specified set of tests in a specified location.
/// Tests are to be written to the location in the order in which they appear in the array.
/// </summary>
/// <param name="tests">Tests to save. Storage parameter on tests must be ignored.</param>
/// <param name="location">Location where tests are to be saved.</param>
/// <param name="projectData">Project information object.</param>
public void Save(ITestElement[] tests, string location, ProjectData projectData)
{
MyTestAssertHelper.ArrayNotNullOrEmpty(tests, "tests");
MyTestAssertHelper.StringNotNullOrEmpty(location, "location");
// Open the test file on disk
FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
using (StreamWriter sw = new StreamWriter(fs))
{
// Go Through all the tests and save them into the previously opened file
foreach (ITestElement testelem in tests)
{
MyTest test = testelem as MyTest;
sw.WriteLine("{0},{1},{2}", test.Name, test.Description, test.CommandLine);
}
}
}
/// <summary>
/// Merges results arrived from the wire (never null) with results in memory (may be null)
/// </summary>
/// <param name="inMemory"></param>
/// <param name="fromTheWire"></param>
/// <returns>result to be put in memory, never null</returns>
public TestResult MergeResults(TestResult inMemory, TestResultMessage fromTheWire)
{
TestResult resultFromWire = fromTheWire as TestResult;
if ((resultFromWire == null) || (fromTheWire == null))
throw new EqtDataException("MereResults");
// If the in memory result is not there yet, we need to
// create one for test framework to work with
if (inMemory == null)
{
TestResult mem = new MyTestResult(new ComputerInfo(fromTheWire.ComputerName), fromTheWire.Id.RunId, (MyTest)resultFromWire.Test);
mem.Outcome = resultFromWire.Outcome;
return mem; // Send it back for use by test framework
}
if (fromTheWire != null)
return resultFromWire;
else
return inMemory;
}
/// <summary>
/// This is called when the TIP needs to stop watching for changes in the location specified.
/// It should only start watching again when Load() is called. For the sample, this is not
/// relevant (since we aren't watching for changes)
/// </summary>
/// <param name="location">Location to stop listening for changes</param>
/// <param name="warningHandler">Warning handler to be called when warnings occur</param>
public void Unload(string location, IWarningHandler warningHandler)
{ }
/// <summary>
/// When called, the TIP should stop listening for changes in ALL currently
/// watched locations (Again, not relvant since we are not watching for changes)
/// </summary>
public void Reset()
{ }
/// <summary>
/// When the TMI is removing a run, this method is called to allow you to remove
/// or clear up any state related to storage of result (eg in a database)
/// </summary>
/// <param name="runId"></param>
public void BeforeRemoveTestRun(Guid runId)
{
}
/// <summary>
/// The Standard IDispose.Dispose();
/// </summary>
public void Dispose()
{ }
#endregion
}
}