Gradle multi-project, change default build filename (build.gradle) - build

We have a multiproject with a settings.gradle and no build.gradle in the root project.
The default behaviour of gradle is just look up the settings.gradle file on the top dir and read the build.gradle for every project defined before.
My problem is: depending on the environment where the multiproject has been checked out, I want to run as default "build2.gradle" instead of "build.gradle" when running a build from the root project.
What is the best way to do it??
Thanks

Or for nested multiproject in settings.gradle:
setBuildFileName(rootProject)
def setBuildFileName(project) {
project.children.each { childProject ->
childProject.buildFileName = "${childProject.name}.gradle"
assert childProject.projectDir.isDirectory()
assert childProject.buildFile.isFile()
setBuildFileName(childProject)
}
}

ok, done...
In settings.gradle:
String myFileName = "build2.gradle"
rootProject.buildFileName = myFileName
rootProject.children.each { project ->
project.buildFileName = myFileName
assert project.projectDir.isDirectory()
assert project.buildFile.isFile()
}

Related

Is it possible to have Elixir's Mix load sources from more than one path?

I have been trying like mad to use config based mocks on Elixir. I have defined my mocked module and placed it inside a ".ex" file under the "test/" directory. Then whenever I run "mix test" it fails to load the module. However if I move the mock under "lib/" then everything works just fine. So I was wondering if there is something I'm missing on my configuration and file structure OR if there is a way to tell "mix" to look for source files in another directory in addition to "lib/".
File structure:
my_app/
|
+ -- lib/
| my_lib.ex
| my_service.ex
|
+ ---test/
| test_helper.ex
| my_service_mock.ex
| my_lib_test.exs
|
+----config/
config.exs
test.exs
prod.exs
dev.exs
config/dev.exs
import Config
config :my_app, my_service: MyApp.MyService
config/test.exs
import Config
config :my_app, my_service: MyApp.MyServiceMock
my_lib.ex
defmodule MyLib do
#my_service Application.get_env(:my_app, :my_service)
def do_something, do: #my_service.do_something_else
end
my_service.ex
defmodule MyApp.MyService do
def do_something_else, do: { :ok, "Running business task" }
end
my_service_mock.ex
defmodule MyApp.MyServiceMock do
def do_something_else, do: { :ok, "Faking business task" }
end
my_lib_test.ex
defmodule MyApp.MyLibTest do
use ExUnit.Case
alias MyApp.MyLib
test "MyList.do_something/0 should do it's thing" do
assert { :ok, "Faking business task" } = MyLib.do_something
end
end
The command "mix test" fails with the following error:
== Compilation error in file lib/my_lib.ex ==
** (UndefinedFunctionError) function MyApp.MyServiceMock.do_something_else/0 is undefined (module MyApp.MyServiceMock is not available)
MyApp.MyServiceMock.do_something_else()
lib/my_lib.ex:3: (module)
(stdlib 3.14) erl_eval.erl:680: :erl_eval.do_apply/6
I'm running elixir 1.11.2.
Well, I finally found out the solution on this post on Elixir Forum: https://elixirforum.com/t/load-module-during-test/7400
It turns out there is a variable in the "Mix.Project" that specifies the paths for the sources:
So in my "mix.exs" I did the following:
def project do
[
...
elixirc_paths: elixirc_paths(Mix.env),
...
]
end
defp elixirc_paths(env_name) do
case env_name do
:test -> ["lib", "test/mockery"]
_ -> ["lib"]
end
end
Of course I added the directory "test/mockery/" and moved "MyApp.MyServiceMock" there...

meson add existing dll as dependency

I want to add a dll as dependency to my own project under Windows.
I tried following:
lept_include = include_directories('../libs/tesseract')
lept_lib = '/g/programming/meson/libs/tesseract/liblept-5.dll'
lept_dep = declare_dependency(link_with:lept_lib, include_directories:lept_include)
executable('test1', 'main.cpp', dependencies: [boost_dep, lept_dep])
but got this error:
..\meson.build:25:0: ERROR: '/g/programming/meson/libs/tesseract/liblept-5.dll' is not a target.
I also tried this but dit not work either:
cc = meson.get_compiler('cpp')
lib_l1 = cc.find_library('liblept-5.dll', dirs : ['/g/programming/meson/libs/tesseract'])
lib_l2 = cc.find_library('liblept-5', dirs : ['/g/programming/meson/libs/tesseract'])
lib_l3 = cc.find_library('lept-5.dll', dirs : ['/g/programming/meson/libs/tesseract'])
lib_l4 = cc.find_library('lept-5', dirs : ['/g/programming/meson/libs/tesseract'])
How can I achieve this?
thanks
Amazingly lib_l4 = cc.find_library('lept-5', dirs : ['/cygdrive/g/programming/meson/libs/tesseract']) is working now. At first I was using MSYS for windows, now I tried CYGWIN and the lib was found.

making unit test binaries using scons with g++ and gtest

I am not able sucessfully build the the project using scons, g++ and gtest. I want to use gtest as unit test. My project looks like below:
project
| -SConstruct
| -src
| -name.hh
| -name.cc
| -main.cc
| -gtest
| -/src/gtest_name.hh
| -/src/gtest_name.cc
| -/src/gtest_main.cc
Inside SConstruct for project building, I have following code:
program_srcs = ['name.cc']
cpppath = ['./src']
libpath = ['.', 'path_to_third_party_lib']
libs = ['thirdlib']
pro_env = Environment()
env.Append(CPPPATH = cpppath)
env.Append(LIBS = libs)
env.Append(LIBPATH = libpath)
env.Library('name', program_srcs)
libpath.append('name')
env.Append(LIBPATH = libpath)
env.Program(target = 'NAME', source = [ './src/main.cc']
test_src = ['./gtest/src/gtest_name.cc']
test_env = Environment()
test_env['LIBPATH'] = ['.']
test_env.Program("unit_test", test_src, LIBS=['name'])
Inside gtest_name.cc
include"name.hh"
TEST_F(TESTNAME, testmethod) {
Name name;
ASSERT_EQ(name.get_surname, "MIKE");
}
When I tried to compile and build, it gave following errors for gtest.
g++ -o gtest/src/gtest_name.o -c gtest/src/gtest_name.cc
gtest/src/gtest_name.cc:10:29: error: name.hh: No such file or directory
When I checked for library 'name', it was already constructed. Could you please tell me what the problem is?
You have added the required include search path "src" to the variable CPPPATH, for the environment "env".
But you build the library with the environment "test_env" which doesn't have CPPPATH defined.
That's why the "-I" directive is missing in your compiler call.
Note, that SCons offers a Clone() method for environments. It copies over all current definitions (and builders for example) from one environment to create a new one...this might come in handy here.

Golang: tests and working directory

I'm writing some unit tests for my application in Go. The tests fail however because it cannot find the configuration files. Normally the binary looks for the configuration files in the working directory under the path conf/*.conf.
I figured that browsing to the directory that has conf/ and running go test in it would solve it, but it still reports that the file system cannot find the path specified.
How can I tell go test to use a certain directory as the working directory so that the tests may actually be executed?
You may be able to use the Caller to get the path to the current test source file, like this:
package sample
import (
"testing"
"runtime"
"fmt"
)
func TestGetFilename(t *testing.T) {
_, filename, _, _ := runtime.Caller(0)
t.Logf("Current test filename: %s", filename)
}
I do not believe this is possible. I have not been able to find documentation stating this explicitly, but I believe go test always uses the package directory (containing the go source files) as the working directory.
As a workaround, I compiled the test and execute the test from the current directory.
go test -c && ./<mypackage>.test
Or, if you want a generic command that you can use, you can rename the test file with -o option.
go test -c -o xyz.test && ./xyz.test
While not really convenient, you can always pass it as a command line variable, for example :
package blah_test
import (
"flag"
"fmt"
"os"
"testing"
)
var (
cwd_arg = flag.String("cwd", "", "set cwd")
)
func init() {
flag.Parse()
if *cwd_arg != "" {
if err := os.Chdir(*cwd_arg); err != nil {
fmt.Println("Chdir error:", err)
}
}
}
func TestBlah(t *testing.T) {
t.Errorf("cwd: %+q", *cwd_arg)
}
Then run it like :
┌─ oneofone#Oa [/tmp]
└──➜ go test . -cwd="$PWD"
--- FAIL: TestBlah (0.00 seconds)
blah_test.go:16: cwd: "/tmp"
No matter where the work directory is. It must be under your project Dir. So my solution is
wd, _ := os.Getwd()
for !strings.HasSuffix(wd, "<yourProjectDirName>") {
wd = filepath.Dir(wd)
}
raw, err := ioutil.ReadFile(fmt.Sprintf("%s/src/conf/conf.dev.json", wd))
Your path should always start from your project Dir. Every time you read the file in a package and accessed by main.go or your another package unit test. It will always work.
You can use the os package.
You would want to do something like this
func TestMyFunction(t *testing.T) {
os.Chdir("./path")
//TEST FUNCTION
os.Chdir("..")
}
There are several possibilities in the os package.
To add init function into *_test.go under your test package.
Test package will run this function before test function start.
func init() {
_, filename, _, _ := runtime.Caller(0)
// The ".." may change depending on you folder structure
dir := path.Join(path.Dir(filename), "..")
err := os.Chdir(dir)
if err != nil {
panic(err)
}
}
I know this is an old question but I had the same problem trying to use migrations for the database on my tests, and maybe this solution helps someone.
Since there is no native way of getting the project directory, you could identify some file or directory that you know it's only in the root of the project (in my case, it was the relative directory database/migrations). Once you have this unique relative directory, you could have a function like the following to obtain the project root directory. It just gets the current working directory (assuming it's inside the project's directory) and starts to navigate all the way up until it finds a dir that has the relative directory you know it's on the root of the project:
func FindMyRootDir() string {
workingDirectory, err := os.Getwd()
if err != nil {
panic(err)
}
lastDir := workingDirectory
myUniqueRelativePath := "database/migrations"
for {
currentPath := fmt.Sprintf("%s/%s", lastDir, myUniqueRelativePath)
fi, err := os.Stat(currentPath)
if err == nil {
switch mode := fi.Mode(); {
case mode.IsDir():
return currentPath
}
}
newDir := filepath.Dir(lastDir)
// Ooops, we couldn't find the root dir. Check that your "myUniqueRelativePath" really exists
if newDir == "/" || newDir == lastDir {
return ""
}
lastDir = newDir
}
}
Of course it's not the most beautiful solution, but it works.
I've had a similar problem and found the solution on this blog
Basically you can change the folder that the test is running using a similar function:
package main
import (
"os"
"path"
"runtime"
)
func MakeFunctionRunOnRootFolder() {
_, filename, _, _ := runtime.Caller(0)
// The ".." may change depending on you folder structure
dir := path.Join(path.Dir(filename), "..")
err := os.Chdir(dir)
if err != nil {
panic(err)
}
}
Go 1.20 is getting new -C arguments for "go subcommands" so this should help:
go test -C directory/ ...
It's a common practice in Go to place test fixtures in same package inside testdata folder.
Some examples from standard library:
debug/elf
net/http
image
Also, there is a post from Dave Cheney, where he suggests following code:
f, err := os.Open("testdata/somefixture.json")
I currently use a neat solution for this problem, instead of opening the file directly by calling os.Open(), I use the embed package in a smart way:
First I create a global variable in my root package called:
//go:embed config/* otherdirectories/*
var RootFS embed.FS
Then I just open the files inside my tests by using this global variable, e.g.:
func TestOpenConfig(t *testing.T) {
configFile, err := rootpkg.RootFS.ReadFile("config/env")
if err != nil {
t.Fatalf("unable to open config/env file: %s", err)
}
if string(configFile) != "FOO=bar\n" {
t.Fatalf("config file contents differ from expected: %s", string(configFile))
}
}
This is a neat trick because now you can always work with relative paths from your root package, which is what I used to do in other programming languages.
Of course, this has the restriction that you will need to import your root package, which depending on your package layout might not be ideal because of cyclic imports. If this is your case you might just create a embed.go file inside the config directory itself and call
your configs by name.
One other drawback is that you are embedding test files in your binary, this is probably ok if your test files are not very big, like megabytes big, so I don't really mind this issue.
I also created a repository for illustrating this solution:
https://github.com/VinGarcia/golang-reading-files-from-tests
I would use an Environment Variable for the location of your application. It seems to be the best way when running go tools, as test programs can be run from a temporary location.
// get home dir of app, use MYAPPHOME env var if present, else executable dir.
func exeDir() string {
dir, exists := os.LookupEnv("MYAPPHOME")
if exists {
return dir
} else {
ex, err := os.Executable()
if err != nil {
panic(err)
}
exPath := path.Dir(ex)
return exPath
}
}

Package visibility in Go Unit Tests

Given the following code file (named server.go) in Go:
package glimpse
func SplitHeader() string {
return "hi there"
}
and the accompanying test file (server_test.go):
package glimpse
import (
"testing"
)
func TestSplitHeader(t *testing.T) {
answer := SplitHeader()
if answer == "" {
t.Error("No return value")
}
}
Why is it the following command:
go test server_test.go
returns
# command-line-arguments
./server_test.go:9: undefined: SplitHeader
I'm certainly missing something catastrophically obvious.
Use only
$ go test
from within the package directory to perform testing. If you name specific files as an argument to go test, then only those file will be considered for the build of the test binary. That explains the 'undefined' error.
As an alternative, use "import path" as an argument to go test instead, for example
$ go test foo.com/glimpse