#!/usr/bin/env ruby # This test checks whether the packages create a dependency cycle. require 'find' require_relative '../lib/const' require_relative '../lib/color' require_relative '../lib/package' @all_pkgs = {} $LOAD_PATH.unshift '../lib' puts "Running dependency cycle tests...\n".yellow # Loads all packages Dir['../packages/*.rb'].each do |filename| name = File.basename(filename, '.rb') pkg = Package.load_package(filename, name) @all_pkgs[name] = pkg end # Looking for cycles. @path will keep the current dependency path. # @state will store :on_path for vertices on the current dependency path # and :visited for vertices that have already been checked not to lead to # cycles. @failed = 0 @state = {} @path = [] @uniq_path = [] def dfs(pkg) @path.push(pkg.name) if @state[pkg] == :on_path while @path.first != @path.last @path.shift end if not @uniq_path.include? @path.to_s and @path.to_s.include? ',' @uniq_path.push(@path.to_s) @failed += 1 end elsif @state[pkg] == nil @state[pkg] = :on_path if pkg.dependencies pkg.dependencies.each do |name, v| if name != pkg.name dfs(@all_pkgs[name]) end end end @state[pkg] = :visited end @path.pop end # Calls dfs for every path @all_pkgs.each do |name, pkg| dfs(pkg) end # Display dependency cycles @uniq_path.sort.each do |path| puts path.lightred end @cycles = "cycles" @cycles = "cycle" if @failed == 1 if @failed > 0 abort "\n#{@failed} dependency #{@cycles} found.".lightred else puts "\nNo dependency cycles found.".lightgreen end