github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cmd/roachtest/django.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package main
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"regexp"
    17  )
    18  
    19  var djangoReleaseTagRegex = regexp.MustCompile(`^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<point>\d+)$`)
    20  var djangoCockroachDBReleaseTagRegex = regexp.MustCompile(`^(?P<major>\d+)\.(?P<minor>\d+)$`)
    21  
    22  func registerDjango(r *testRegistry) {
    23  	runDjango := func(
    24  		ctx context.Context,
    25  		t *test,
    26  		c *cluster,
    27  	) {
    28  		if c.isLocal() {
    29  			t.Fatal("cannot be run in local mode")
    30  		}
    31  		node := c.Node(1)
    32  		t.Status("setting up cockroach")
    33  		c.Put(ctx, cockroach, "./cockroach", c.All())
    34  		c.Start(ctx, t, c.All())
    35  
    36  		version, err := fetchCockroachVersion(ctx, c, node[0])
    37  		if err != nil {
    38  			t.Fatal(err)
    39  		}
    40  
    41  		err = alterZoneConfigAndClusterSettings(ctx, version, c, node[0])
    42  		if err != nil {
    43  			t.Fatal(err)
    44  		}
    45  
    46  		t.Status("cloning django and installing prerequisites")
    47  
    48  		if err := repeatRunE(
    49  			ctx, c, node, "update apt-get",
    50  			`
    51  				sudo add-apt-repository ppa:deadsnakes/ppa &&
    52  				sudo apt-get -qq update`,
    53  		); err != nil {
    54  			t.Fatal(err)
    55  		}
    56  
    57  		if err := repeatRunE(
    58  			ctx,
    59  			c,
    60  			node,
    61  			"install dependencies",
    62  			`sudo apt-get -qq install make python3.6 libpq-dev python3.6-dev gcc python3-setuptools python-setuptools build-essential`,
    63  		); err != nil {
    64  			t.Fatal(err)
    65  		}
    66  
    67  		if err := repeatRunE(
    68  			ctx, c, node, "set python3.6 as default", `
    69      		sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1
    70      		sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2
    71      		sudo update-alternatives --config python3`,
    72  		); err != nil {
    73  			t.Fatal(err)
    74  		}
    75  
    76  		if err := repeatRunE(
    77  			ctx, c, node, "install pip",
    78  			`curl https://bootstrap.pypa.io/get-pip.py | sudo -H python3.6`,
    79  		); err != nil {
    80  			t.Fatal(err)
    81  		}
    82  
    83  		if err := repeatRunE(
    84  			ctx,
    85  			c,
    86  			node,
    87  			"install pytest",
    88  			`sudo pip3 install pytest pytest-xdist psycopg2`,
    89  		); err != nil {
    90  			t.Fatal(err)
    91  		}
    92  
    93  		if err := repeatRunE(
    94  			ctx, c, node, "remove old django", `rm -rf /mnt/data1/django`,
    95  		); err != nil {
    96  			t.Fatal(err)
    97  		}
    98  
    99  		djangoLatestTag, err := repeatGetLatestTag(
   100  			ctx, c, "django", "django", djangoReleaseTagRegex,
   101  		)
   102  		if err != nil {
   103  			t.Fatal(err)
   104  		}
   105  		c.l.Printf("Latest Django release is %s.", djangoLatestTag)
   106  
   107  		if err := repeatGitCloneE(
   108  			ctx,
   109  			t.l,
   110  			c,
   111  			"https://github.com/django/django/",
   112  			"/mnt/data1/django",
   113  			djangoLatestTag,
   114  			node,
   115  		); err != nil {
   116  			t.Fatal(err)
   117  		}
   118  
   119  		djangoCockroachDBLatestTag, err := repeatGetLatestTag(
   120  			ctx, c, "cockroachdb", "django-cockroachdb", djangoCockroachDBReleaseTagRegex,
   121  		)
   122  		if err != nil {
   123  			t.Fatal(err)
   124  		}
   125  		c.l.Printf("Latest django-cockroachdb release is %s.", djangoCockroachDBLatestTag)
   126  
   127  		if err := repeatGitCloneE(
   128  			ctx,
   129  			t.l,
   130  			c,
   131  			"https://github.com/cockroachdb/django-cockroachdb",
   132  			"/mnt/data1/django/tests/django-cockroachdb",
   133  			djangoCockroachDBLatestTag,
   134  			node,
   135  		); err != nil {
   136  			t.Fatal(err)
   137  		}
   138  
   139  		if err := repeatRunE(
   140  			ctx, c, node, "install django's dependencies", `
   141  				cd /mnt/data1/django/tests &&
   142  				sudo pip3 install -e .. &&
   143  				sudo pip3 install -r requirements/py3.txt &&
   144  				sudo pip3 install -r requirements/postgres.txt`,
   145  		); err != nil {
   146  			t.Fatal(err)
   147  		}
   148  
   149  		if err := repeatRunE(
   150  			ctx, c, node, "install django-cockroachdb", `
   151  					cd /mnt/data1/django/tests/django-cockroachdb/ &&
   152  					sudo pip3 install .`,
   153  		); err != nil {
   154  			t.Fatal(err)
   155  		}
   156  
   157  		// Write the cockroach config into the test suite to use.
   158  		if err := repeatRunE(
   159  			ctx, c, node, "configuring tests to use cockroach",
   160  			fmt.Sprintf(
   161  				"echo \"%s\" > /mnt/data1/django/tests/cockroach_settings.py",
   162  				cockroachDjangoSettings,
   163  			),
   164  		); err != nil {
   165  			t.Fatal(err)
   166  		}
   167  
   168  		blacklistName, expectedFailureList, ignoredlistName, ignoredlist := djangoBlacklists.getLists(version)
   169  		if expectedFailureList == nil {
   170  			t.Fatalf("No django blacklist defined for cockroach version %s", version)
   171  		}
   172  		if ignoredlist == nil {
   173  			t.Fatalf("No django ignorelist defined for cockroach version %s", version)
   174  		}
   175  		c.l.Printf("Running cockroach version %s, using blacklist %s, using ignoredlist %s",
   176  			version, blacklistName, ignoredlistName)
   177  
   178  		// TODO (rohany): move this to a file backed buffer if the output becomes
   179  		//  too large.
   180  		var fullTestResults []byte
   181  		for _, testName := range enabledDjangoTests {
   182  			t.Status("Running django test app", testName)
   183  			// Running the test suite is expected to error out, so swallow the error.
   184  			rawResults, _ := c.RunWithBuffer(
   185  				ctx, t.l, node, fmt.Sprintf(djangoRunTestCmd, testName))
   186  			fullTestResults = append(fullTestResults, rawResults...)
   187  			c.l.Printf("Test results for app %s: %s", testName, rawResults)
   188  			c.l.Printf("Test stdout for app %s:", testName)
   189  			if err := c.RunL(
   190  				ctx, t.l, node, fmt.Sprintf("cd /mnt/data1/django/tests && cat %s.stdout", testName),
   191  			); err != nil {
   192  				t.Fatal(err)
   193  			}
   194  		}
   195  		t.Status("collating test results")
   196  
   197  		results := newORMTestsResults()
   198  		results.parsePythonUnitTestOutput(fullTestResults, expectedFailureList, ignoredlist)
   199  		results.summarizeAll(
   200  			t, "django" /* ormName */, blacklistName,
   201  			expectedFailureList, version, djangoLatestTag,
   202  		)
   203  	}
   204  
   205  	r.Add(testSpec{
   206  		MinVersion: "v19.2.0",
   207  		Name:       "django",
   208  		Owner:      OwnerAppDev,
   209  		Cluster:    makeClusterSpec(1, cpu(16)),
   210  		Tags:       []string{`default`, `orm`},
   211  		Run: func(ctx context.Context, t *test, c *cluster) {
   212  			runDjango(ctx, t, c)
   213  		},
   214  	})
   215  }
   216  
   217  // Test results are only in stderr, so stdout is redirected and printed later.
   218  const djangoRunTestCmd = `
   219  cd /mnt/data1/django/tests &&
   220  python3 runtests.py %[1]s --settings cockroach_settings --parallel 1 -v 2 > %[1]s.stdout
   221  `
   222  
   223  const cockroachDjangoSettings = `
   224  DATABASES = {
   225      'default': {
   226          'ENGINE': 'django_cockroachdb',
   227          'NAME' : 'django_tests',
   228          'USER' : 'root',
   229          'PASSWORD' : '',
   230          'HOST': 'localhost',
   231          'PORT' : 26257,
   232      },
   233  }
   234  SECRET_KEY = 'django_tests_secret_key'
   235  PASSWORD_HASHERS = [
   236      'django.contrib.auth.hashers.MD5PasswordHasher',
   237  ]
   238  `