Для обнаружения Linux пространств имен при определенных условиях мой пакет с открытым исходным кодом Golang lxkns должен повторно выполнить приложение, в котором он используется как новый дочерний процесс, чтобы иметь возможность переключите пространства имен монтирования до того, как время выполнения Golang увеличится. Работа Linux монтирования пространств имен делает невозможным переключение их из Golang приложений после того, как среда выполнения ускорила потоки ОС.
Это означает, что исходный процесс "P" перезапускается. - запускает копию себя как дочерний «C» ( reexe c пакет), передавая специальную индикацию через дочернюю среду, которая сигнализирует дочернему элементу только для запуска указанного c " функция action, принадлежащая включенному пакету «lxkns» (подробности см. ниже), вместо того, чтобы нормально запускать все приложение (избегая бесконечных рекурсивно порождаемых потомков).
forkchild := exec.Command("/proc/self/exe")
forkchild.Start()
...
forkchild.Wait()
В данный момент я вызываю покрытие тестирует из кода VisualStudio, который запускает:
go test -timeout 30s -coverprofile=/tmp/vscode-goXXXXX/go-code-cover github.com/thediveo/lxkns
Итак, «P» повторно выполняет копию «C» самого себя и говорит ему выполнить какое-то действие «A», вывести некоторый результат в стандартный вывод, а затем немедленно прекратить. «P» ожидает вывода «C», анализирует его и затем продолжает выполнение программы.
В модульном тесте используется Ginkgo / Gomega и выделенный TestMain
, чтобы поймать, когда Тест перезапускается как дочерний, чтобы запустить только запрошенную функцию «действие».
package lxkns
import (
"os"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/thediveo/gons/reexec"
)
func TestMain(m *testing.M) {
// Ensure that the registered handler is run in the re-executed child. This
// won't trigger the handler while we're in the parent, because the
// parent's Arg[0] won't match the name of our handler.
reexec.CheckAction()
os.Exit(m.Run())
}
func TestLinuxKernelNamespaces(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "lxkns package")
}
Я также хотел бы создать данные покрытия кода из повторно выполненного дочернего процесса.
- Можно ли включить покрытие кода из самой тестируемой программы и как это сделать?
- Можно ли затем добавить данные покрытия кода, записанные ребенком, в данные покрытия покрытия родительский процесс "P"?
- Записывает ли среда выполнения Golang только данные покрытия при выходе и перезаписывает ли указанный файл или добавляет? (Я уже был бы рад за указатель на соответствующие источники времени выполнения.)
Примечание: переключение пространств имен монтирования не будет конфликтовать с созданием файлов покрытия в новых пространствах имен монтирования в моих тестовых примерах. Причина в том, что эти пространства имен тестового монтирования являются копиями начальных пространств имен монтирования, поэтому создание нового файла будет также отображаться в файловой системе в обычном режиме.