include("generic/MatRing-test.jl")
include("generic/NCPoly-test.jl")
include("generic/FreeAssociativeAlgebra-test.jl")
include("generic/FreeAssociativeAlgebraGroebner-test.jl")

@testset "NCRings.oftype" begin
   F = GF(3)
   Fx, x = polynomial_ring(F, "x")
   z = oftype(x, 3)
   @test z == Fx(3)
   @test parent(z) === Fx
end

@testset "NCRings.powers" begin

   # non-commutative rings
   A = matrix_ring(ZZ, rand(1:9))
   a = rand(A, 1:9)

   B, _ = polynomial_ring(A, "y")
   b = rand(B, 1:9, 1:9)

   # matrices
   n = rand(1:9)
   C = matrix_space(ZZ, n, n)
   c = rand(C, 1:9)

   # commutative rings
   d = rand() * rand(-9:9)
   e = rand(big.(-9:9))
   f = rand(1:9)//rand(1:9)

   G, _ = polynomial_ring(ZZ, "x")
   g = rand(G, 1:9, 1:9)

   @testset "$T" for (x, T) in (x => string(nameof(typeof(x))) for x in (a, b, c, d, e, f, g))
      @test_throws DomainError powers(x, -rand(1:100))

      S = powers(x, 0)
      @test length(S) == 1
      @test isone(S[1])

      P = powers(x, 1)
      @test length(P) == 2
      @test isone(P[1])
      @test P[2] == x

      n = rand(2:9)
      Q = powers(x, n)
      @test length(Q) == n+1
      @test Q[1:2] == P
      @test Q[3] == x*x
   end

   # powers must error out on non-square matrices
   M = matrix_space(ZZ, 2, rand(3:9))
   @test_throws DomainError powers(rand(M, 1:9), rand(1:9))
end

@testset "dot" begin
  dot = AbstractAlgebra.LinearAlgebra.dot

  Qx, x  = QQ["x"]
  @test dot([x, x^2], [1, 1]) == x + x^2
  @test dot([x, x^2], Rational{BigInt}[1, 1]) == x + x^2
  @test dot([1, 1], [x, x^2]) == x + x^2
  @test dot(Rational{BigInt}[1, 1], [x, x^2]) == x + x^2
  @test dot([x], [x^2]) == x^3

  R = matrix_ring(QQ, 2)
  x = R([1 2; 3 4])
  @test dot([x, x^2], [1, 1]) == x + x^2
  @test dot([x, x^2], Rational{BigInt}[1, 1]) == x + x^2
  @test dot([1, 1], [x, x^2]) == x + x^2
  @test dot(Rational{BigInt}[1, 1], [x, x^2]) == x + x^2
  @test dot([x], [x^2]) == x^3
end
