/** * @brief initialization WITHOUT Visual Studio services available. */ public CTestAdapterPackage() { if (null != Instance) { /// @todo give some error here! } Instance = this; // main DTE object this._dte = (DTE)Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider.GetService(typeof(DTE)); // basic solution events this._log = new CTestAdapterLog(); this._sol = new SolutionEventListener(Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider); this._sol.SolutionLoaded += this.SolutionLoaded; this._sol.SolutionUnloaded += this.SolutionUnloaded; // cmake cache & cmake test file this._config = new CTestAdapterConfig(); this._cmakeCache = new CMakeCache(this._log); this._cMakeCacheWatcher = new CMakeCacheWatcher(this._log); this._cMakeCacheWatcher.CacheFileChanged += this.OnCMakeCacheChanged; // test container discovery and management this._containerManager = new TestContainerManager(this, this._log); this._activeConfigurationTimer = new System.Timers.Timer(CTestAdapterPackage.ConfigurationTimerIntervalMs); this._activeConfigurationTimer.Elapsed += this.UpdateActiveConfiguration; this._containerManager.TestContainersChanged += this.OnTestContainersChanged; this.SetValidRelease(); }
public static CTestTestCollection FindAllTestsWithCtest(CTestAdapterConfig cfg) { if (null == cfg) { return(null); } if (!Directory.Exists(cfg.CacheDir)) { return(null); } if (!File.Exists(cfg.CTestExecutable)) { return(null); } var collection = new CTestTestCollection(); var collector = new CTestTestCollector { CTestExecutable = cfg.CTestExecutable, CTestWorkingDir = cfg.CacheDir, CurrentActiveConfig = cfg.ActiveConfiguration }; collector.CollectTestCases(collection); return(collection); }
private void UpdateActiveConfiguration(object sender, ElapsedEventArgs elapsedEventArgs) { if (!this._ctestAdapterEnabled) { return; } // set current active configuration var p = this._dte.Solution.SolutionBuild; if (null == p) { return; } var sc = p.ActiveConfiguration; if (null == sc) { return; } var name = sc.Name; if (this._config.ActiveConfiguration == name) { return; } this._config.ActiveConfiguration = name; CTestAdapterConfig.WriteToDisk(this._config); this._containerManager.FindTestContainers(); }
public static CTestAdapterConfig ReadFromDisk(string file) { if (!File.Exists(file)) { return(null); } var ser = new XmlSerializer(typeof(CTestAdapterConfig)); while (CTestAdapterConfig.IsFileLocked(file)) { Thread.Sleep(50); } var str = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); var cfg = (CTestAdapterConfig)ser.Deserialize(str); str.Close(); if (null == cfg) { return(null); } if (cfg._configFileName != file) { // @todo give some message here? } return(cfg); }
public static CTestAdapterConfig ReadFromCache(string dir) { if (!Directory.Exists(dir)) { return(null); } ILog log = null; var pkg = CTestAdapterPackage.Instance; if (null != pkg) { log = pkg.Logger; } var cache = new CMakeCache(log); cache.LoadCMakeCache(Path.Combine(dir, Constants.CMakeCacheFilename)); if (!cache.IsLoaded) { return(null); } var cfg = new CTestAdapterConfig { // unfortunately we cannot set the active configuration here, // a fallback will be used when parsing CMakeConfigurationTypes = cache[Constants.CMakeCacheKey_CofigurationTypes], CTestExecutable = cache[Constants.CMakeCacheKey_CTestCommand], CacheDir = cache[Constants.CMakeCacheKey_CacheFileDir] }; return(cfg); }
private bool SetupEnvironment(string source) { var cacheDir = TestContainerHelper.FindCMakeCacheDirectory(source); this._config = CTestAdapterConfig.ReadFromDisk(Path.Combine(cacheDir, Constants.CTestAdapterConfigFileName)) ?? CTestAdapterConfig.ReadFromCache(cacheDir); if (this._config == null) { this.Log(TestMessageLevel.Error, "could not initialize environment"); return(false); } return(true); }
private void OnCMakeCacheChanged() { var cacheFileName = Path.Combine(this._cMakeCacheWatcher.CMakeCacheDirectory, this._cMakeCacheWatcher.CMakeCacheFile); var testFileName = Path.Combine(this._cMakeCacheWatcher.CMakeCacheDirectory, Constants.CTestTestFileName); this._cmakeCache.LoadCMakeCache(cacheFileName); var enabled = true; if (!this._cmakeCache.IsLoaded) { this.Log(LogLevel.Warning, "OnCMakeCacheChanged (cache not loaded)"); enabled = false; } if (!File.Exists(testFileName)) { this.Log(LogLevel.Warning, "OnCMakeCacheChanged file not found: " + testFileName); enabled = false; } if (this._cmakeCache[Constants.CMakeCacheKey_CTestCommand] == string.Empty) { this.Log(LogLevel.Warning, "OnCMakeCacheChanged ctest not found in cache"); enabled = false; } var ctest = this._cmakeCache[Constants.CMakeCacheKey_CTestCommand]; if (!File.Exists(ctest)) { this.Log(LogLevel.Warning, "OnCMakeCacheChanged ctest executable not found: " + ctest); enabled = false; } this._config.CTestExecutable = ctest; this._config.CMakeConfigurationTypes = this._cmakeCache[Constants.CMakeCacheKey_CofigurationTypes]; CTestAdapterConfig.WriteToDisk(this._config); if (this._ctestAdapterEnabled != enabled) { this.CTestAdapterEnabled = enabled; } this._containerManager.FindTestContainers(); }
public static void WriteToDisk(CTestAdapterConfig cfg) { if (!cfg._dirty) { return; } if (!Directory.Exists(cfg.CacheDir)) { return; } var ser = new XmlSerializer(typeof(CTestAdapterConfig)); while (CTestAdapterConfig.IsFileLocked(cfg._configFileName)) { Thread.Sleep(50); } var str = new StreamWriter(cfg._configFileName); ser.Serialize(str, cfg); str.Close(); cfg._dirty = false; }
public void LoadCMakeCache(string fileName) { this._cmakeCacheFile = fileName; if (null == this._cmakeCacheFile || !File.Exists(this._cmakeCacheFile)) { this.Log(LogLevel.Debug, "LoadCMakeCache: clearing cmake CMakeCache"); this._cacheEntries.Clear(); return; } var newInfo = new FileInfo(this._cmakeCacheFile); if (this._cmakeCacheInfo != null) { this.Log(LogLevel.Debug, "LoadCMakeCache: comparing already loaded CMakeCache"); if (this._cmakeCacheInfo.FullName == newInfo.FullName && this._cmakeCacheInfo.LastWriteTime == newInfo.LastWriteTime && newInfo.Exists) { this.Log(LogLevel.Debug, "LoadCMakeCache: CMakeCache did not change, not reloading"); return; } } this.Log(LogLevel.Debug, "LoadCMakeCache: loading CMakeCache from \"" + this._cmakeCacheFile + "\""); this._cmakeCacheInfo = newInfo; this._cacheEntries.Clear(); if (!File.Exists(this._cmakeCacheFile)) { this.Log(LogLevel.Error, "LoadCMakeCache: CMakeCache not found at:\"" + this._cmakeCacheFile + "\""); return; } while (CTestAdapterConfig.IsFileLocked(this._cmakeCacheFile)) { Thread.Sleep(50); } var stream = new FileStream(this._cmakeCacheFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var r = new StreamReader(stream); while (!r.EndOfStream) { var line = r.ReadLine(); if (null == line) { continue; } line = line.TrimStart(' '); if (line.Length == 0 || line.StartsWith("#") || line.StartsWith("//")) { continue; } var c = CMakeCache.CacheEntryRegex.Split(line); if (c.Length != 5) { this.Log(LogLevel.Warning, "LoadCMakeCache: CMakeCache load: element count != 5: (" + c.Length + ")" + line); var count = 0; foreach (var asdf in c) { this.Log(LogLevel.Warning, "v" + count + ": " + asdf); count++; } continue; } CMakeCacheEntryType myType; if (!Enum.TryParse(c[2], out myType)) { this.Log(LogLevel.Error, "LoadCMakeCache: cache load: error parsing enum Type: " + c[2]); continue; } var entry = new CMakeCacheEntry() { Name = c[1], Value = c[3] }; if (entry.Name.StartsWith("\"") && entry.Name.Length > 2) { entry.Name = entry.Name.Substring(1, entry.Name.Length - 2); } this._cacheEntries.Add(entry.Name, entry); } r.Close(); stream.Close(); r.Dispose(); stream.Dispose(); }
public void DiscoverTests(IEnumerable <string> sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink) { this._log = logger; this.Log(TestMessageLevel.Informational, "discovering ..."); var v = sources as IList <string> ?? sources.ToList(); // verify we have a CMakeCache.txt directory var cacheDir = TestContainerHelper.FindCMakeCacheDirectory(v.First()); if (!cacheDir.Any()) { this.Log(TestMessageLevel.Informational, "cmake cache not found"); return; } // read parameters var cfg = CTestAdapterConfig.ReadFromDisk(Path.Combine(cacheDir, Constants.CTestAdapterConfigFileName)) ?? CTestAdapterConfig.ReadFromCache(cacheDir); if (null == cfg) { this.Log(TestMessageLevel.Error, "could not create CTestAdapterConfig"); return; } // make sure a configuration is set if (!cfg.ActiveConfiguration.Any()) { if (cfg.TrySetActiveConfigFromConfigTypes()) { this.Log(TestMessageLevel.Warning, "Configuration fallback to: " + cfg.ActiveConfiguration); } else { this.Log(TestMessageLevel.Error, "could not set Configuration"); return; } } this.Log(TestMessageLevel.Informational, "using configuration: " + cfg.ActiveConfiguration); // make sure we have a ctest executable if (!File.Exists(cfg.CTestExecutable)) { cfg.CTestExecutable = TestContainerHelper.FindCTestExe(cfg.CacheDir); } if (!File.Exists(cfg.CTestExecutable)) { this.Log(TestMessageLevel.Error, "ctest not found, tried: \"" + cfg.CTestExecutable + "\""); return; } this.Log(TestMessageLevel.Informational, "using ctest binary: " + cfg.CTestExecutable); // collect all existing tests by executing ctest var collection = TestContainerHelper.FindAllTestsWithCtest(cfg); foreach (var source in v) { var cases = TestContainerHelper.ParseTestContainerFile(source, this._log, collection, cfg.ActiveConfiguration); foreach (var c in cases) { discoverySink.SendTestCase(c.Value); } } this.Log(TestMessageLevel.Informational, "discovering done"); }