text:
"""
Tests for the control service REST API.
"""

import socket
from contextlib import closing
from json import loads

from json import dumps

from twisted.trial.unittest import TestCase
from twisted.python.filepath import FilePath
from twisted.internet.defer import gatherResults

from treq import get, post, content

from eliot import Message

from ...testtools import (
    loop_until, random_name,
)
from ..testtools import (
    require_cluster, require_moving_backend, create_dataset,
    create_python_container
)

CURRENT_DIRECTORY = FilePath(__file__).parent()

def verify_socket(host, port):
    """
    Wait until the destionation can be connected to.

    :param bytes host: Host to connect to.
    :param int port: Port to connect to.

    :return Deferred: Firing when connection is possible.
    """
    def can_connect():
        with closing(socket.socket()) as s:
            conn = s.connect_ex((host, port))
            Message.new(
                message_type="acceptance:verify_socket",
                host=host,
                port=port,
                result=conn,
            ).write()
            return conn == 0

    dl = loop_until(can_connect)
    return dl

class ContainerAPITests(TestCase):
    """
    Tests for the container API.
    """
    def _create_container(self, cluster):
        """
        Create a container listening on port 8080.

        :return: ``Deferred`` firing with a container dictionary once the
            container is up and running.
        """
        d = create_python_container(
            self, cluster, {
                u"ports": [{u"internal": 8080, u"external": 8080}],
                u"node_uuid": cluster.nodes[0].uuid,
            }, CURRENT_DIRECTORY.child(b"hellohttp.py"))

        def check_result(response):
            dl = verify_socket(cluster.nodes[0].public_address, 8080)
            dl.addCallback(lambda _: response)
            return dl

        d.addCallback(check_result)
        return d

    @require_cluster(1)
    def test_create_container_with_ports(self, cluster):
        """
        Create a container including port mappings on a single-node cluster.
        """
        return self._create_container(cluster)

    @require_cluster(1)
    def test_create_container_with_environment(self, cluster):
        """
        If environment variables are specified when creating a container,
        those variables are available in the container's environment.
        """
        environment = {u"XBLOO": u"YBLAH", u"ZBLOO": u"ZEBRA"}

        d = create_python_container(
            self, cluster, {
                u"ports": [{u"internal": 8080, u"external": 8080}],
                u"node_uuid": cluster.nodes[0].uuid,
                u"environment": environment,
            }, CURRENT_DIRECTORY.child(b"envhttp.py"))

        def checked(_):
            host = cluster.nodes[0].public_address
            d = self.query_http_server(host, 8080)
            d.addCallback(lambda data: dict(loads(data)))
            return d
        d.addCallback(checked)

        d.addCallback(
            lambda response:
                self.assertDictContainsSubset(environment, response)
        )
        return d

    @require_moving_backend
    @require_cluster(2)
    def test_move_container_with_dataset(self, cluster):
        """
        Create a container with an attached dataset, issue API call
        to move the container. Wait until we can connect to the running
        container on the new host and verify the data has moved with it.
        """
        data = {u"the data": u"it moves"}
        post_data = {"data": dumps(data)}
        node1, node2 = cluster.nodes
        container_name = random_name(self)
        creating_dataset = create_dataset(self, cluster)

        def create_container(dataset):
            d = create_python_container(
                self, cluster, {
                    u"name": container_name,
                    u"ports": [{u"internal": 8080, u"external": 8080}],
                    u"node_uuid": node1.uuid,
                    u"volumes": [{u"dataset_id": dataset[u"dataset_id"],
                                  u"mountpoint": u"/data"}],
                }, CURRENT_DIRECTORY.child(b"datahttp.py"),
                additional_arguments=[u"/data"],
            )
            return d
        creating_dataset.addCallback(create_container)
        creating_dataset.addCallback(
            lambda _: self.post_http_server(
                node1.public_address, 8080, post_data)
        )

        def move_container(_):
            moved = cluster.move_container(
                container_name, node2.uuid
            )
            return moved
        creating_dataset.addCallback(move_container)
        creating_dataset.addCallback(
            lambda _: self.assert_http_server(
                node2.public_address, 8080,
                expected_response=post_data["data"])
        )

        return creating_dataset

    @require_cluster(1)
    def test_create_container_with_dataset(self, cluster):
        """
        Create a container with an attached dataset, write some data,
        shut it down, create a new container with same dataset, make sure
        the data is still there.
        """
        data = {u"the data": u"sample written data"}
        post_data = {"data": dumps(data)}
        node = cluster.nodes[0]
        container_name = random_name(self)
        creating_dataset = create_dataset(self, cluster)
        self.dataset_id = None

        def create_container(dataset):
            self.dataset_id = dataset[u"dataset_id"]
            d = create_python_container(
                self, cluster, {
                    u"name": container_name,
                    u"ports": [{u"internal": 8080, u"external": 8080}],
                    u"node_uuid": node.uuid,
                    u"volumes": [{u"dataset_id": self.dataset_id,
                                  u"mountpoint": u"/data"}],
                }, CURRENT_DIRECTORY.child(b"datahttp.py"),
                additional_arguments=[u"/data"],
                cleanup=False,
            )
            return d
        creating_dataset.addCallback(create_container)
        creating_dataset.addCallback(
            lambda _: self.post_http_server(
                node.public_address, 8080, post_data)
        )
        creating_dataset.addCallback(
            lambda _: self.assert_http_server(
                node.public_address, 8080,
                expected_response=post_data["data"])
        )
        creating_dataset.addCallback(
            lambda _: cluster.remove_container(container_name))

        def create_second_container(_):
            d = create_python_container(
                self, cluster, {
                    u"ports": [{u"internal": 8080, u"external": 8081}],
                    u"node_uuid": node.uuid,
                    u"volumes": [{u"dataset_id": self.dataset_id,
                                  u"mountpoint": u"/data"}],
                }, CURRENT_DIRECTORY.child(b"datahttp.py"),
                additional_arguments=[u"/data"],
            )
            return d
        creating_dataset.addCallback(create_second_container)
        creating_dataset.addCallback(
            lambda _: self.assert_http_server(
                node.public_address, 8081,
                expected_response=post_data["data"])
        )
        return creating_dataset

    @require_cluster(1)
    def test_current(self, cluster):
        """
        The current container endpoint includes a currently running container.
        """
        creating = self._create_container(cluster)

        def created(data):
            data[u"running"] = True

            def in_current():
                current = cluster.current_containers()
                current.addCallback(lambda result: data in result)
                return current
            return loop_until(in_current)
        creating.addCallback(created)
        return creating

    def post_http_server(self, host, port, data, expected_response=b"ok"):
        """
        Make a POST request to an HTTP server on the given host and port
        and assert that the response body matches the expected response.

        :param bytes host: Host to connect to.
        :param int port: Port to connect to.
        :param bytes data: The raw request body data.
        :param bytes expected_response: The HTTP response body expected.
            Defaults to b"ok"
        """
        def make_post(host, port, data):
            request = post(
                "http://{host}:{port}".format(host=host, port=port),
                data=data,
                persistent=False
            )

            def failed(failure):
                Message.new(message_type=u"acceptance:http_query_failed",
                            reason=unicode(failure)).write()
                return False
            request.addCallbacks(content, failed)
            return request
        d = verify_socket(host, port)
        d.addCallback(lambda _: loop_until(lambda: make_post(
            host, port, data)))
        d.addCallback(self.assertEqual, expected_response)
        return d

    def query_http_server(self, host, port, path=b""):
        """
        Return the response from a HTTP server.

        We try multiple since it may take a little time for the HTTP
        server to start up.

        :param bytes host: Host to connect to.
        :param int port: Port to connect to.
        :param bytes path: Optional path and query string.

        :return: ``Deferred`` that fires with the body of the response.
        """
        def query():
            req = get(
                "http://{host}:{port}{path}".format(
                    host=host, port=port, path=path),
                persistent=False
            )

            def failed(failure):
                Message.new(message_type=u"acceptance:http_query_failed",
                            reason=unicode(failure)).write()
                return False
            req.addCallbacks(content, failed)
            return req

        d = verify_socket(host, port)
        d.addCallback(lambda _: loop_until(query))
        return d

    def assert_http_server(self, host, port,
                           path=b"", expected_response=b"hi"):

        """
        Assert that a HTTP serving a response with body ``b"hi"`` is running
        at given host and port.

        This can be coupled with code that only conditionally starts up
        the HTTP server via Flocker in order to check if that particular
        setup succeeded.

        :param bytes host: Host to connect to.
        :param int port: Port to connect to.
        :param bytes path: Optional path and query string.
        :param bytes expected_response: The HTTP response body expected.
            Defaults to b"hi"

        :return: ``Deferred`` that fires when assertion has run.
        """
        d = self.query_http_server(host, port, path)
        d.addCallback(self.assertEqual, expected_response)
        return d

    @require_cluster(1)
    def test_non_root_container_can_access_dataset(self, cluster):
        """
        A container running as a user that is not root can write to a
        dataset attached as a volume.
        """
        node = cluster.nodes[0]
        creating_dataset = create_dataset(self, cluster)

        def created_dataset(dataset):
            return create_python_container(
                self, cluster, {
                    u"ports": [{u"internal": 8080, u"external": 8080}],
                    u"node_uuid": node.uuid,
                    u"volumes": [{u"dataset_id": dataset[u"dataset_id"],
                                  u"mountpoint": u"/data"}],
                }, CURRENT_DIRECTORY.child(b"nonrootwritehttp.py"),
                additional_arguments=[u"/data"])
        creating_dataset.addCallback(created_dataset)

        creating_dataset.addCallback(
            lambda _: self.assert_http_server(node.public_address, 8080))
        return creating_dataset

    @require_cluster(2)
    def test_linking(self, cluster):
        """
        A link from an origin container to a destination container allows the
        origin container to establish connections to the destination container
        when the containers are running on different machines using an address
        obtained from ``<ALIAS>_PORT_<PORT>_TCP_{ADDR,PORT}``-style environment
        set in the origin container's environment.
        """
        destination_port = 8080
        origin_port = 8081

        [destination, origin] = cluster.nodes

        running = gatherResults([
            create_python_container(
                self, cluster, {
                    u"ports": [{u"internal": 8080,
                                u"external": destination_port}],
                    u"node_uuid": destination.uuid,
                }, CURRENT_DIRECTORY.child(b"hellohttp.py")),
            create_python_container(
                self, cluster, {
                    u"ports": [{u"internal": 8081,
                                u"external": origin_port}],
                    u"links": [{u"alias": "dest", u"local_port": 80,
                                u"remote_port": destination_port}],
                    u"node_uuid": origin.uuid,
                }, CURRENT_DIRECTORY.child(b"proxyhttp.py")),
            # Wait for the link target container to be accepting connections.
            verify_socket(destination.public_address, destination_port),
            # Wait for the link source container to be accepting connections.
            verify_socket(origin.public_address, origin_port),
            ])

        running.addCallback(
            lambda _: self.assert_http_server(
                origin.public_address, origin_port))
        return running

    @require_cluster(2)
    def test_traffic_routed(self, cluster):
        """
        An application can be accessed even from a connection to a node
        which it is not running on.
        """
        port = 8080

        [destination, origin] = cluster.nodes

        running = gatherResults([
            create_python_container(
                self, cluster, {
                    u"ports": [{u"internal": 8080, u"external": port}],
                    u"node_uuid": destination.uuid,
                }, CURRENT_DIRECTORY.child(b"hellohttp.py")),
            # Wait for the destination to be accepting connections.
            verify_socket(destination.public_address, port),
            # Wait for the origin container to be accepting connections.
            verify_socket(origin.public_address, port),
            ])

        running.addCallback(
            # Connect to the machine where the container is NOT running:
            lambda _: self.assert_http_server(origin.public_address, port))
        return running


text:
<?xml version="1.0" encoding="UTF-8"?>
<LearningStandards>
  <LearningStandardItem xml:lang="en" RefID="A30102F4D34F4981B71570A018901B3C">
    <RefURI>http://corestandards.org/ELA-Literacy/WHST/6-8/2/c/</RefURI>
    <StandardHierarchyLevel>
      <number>6</number>
      <description>Component</description>
    </StandardHierarchyLevel>
    <StatementCodes>
      <StatementCode>CCSS.ELA-Literacy.WHST.6-8.2c</StatementCode>
    </StatementCodes>
    <Statements>
      <Statement>Use appropriate and varied transitions to create cohesion and clarify the relationships among ideas and concepts.</Statement>
    </Statements>
    <GradeLevels>
      <GradeLevel>06</GradeLevel>
      <GradeLevel>07</GradeLevel>
      <GradeLevel>08</GradeLevel>
    </GradeLevels>
    <LearningStandardDocumentRefId>0FAC40650F514a459951A657F942B845</LearningStandardDocumentRefId>
    <RelatedLearningStandardItems>
      <LearningStandardItemRefId RelationshipType="childOf">33814B9CAC90431999D0C2E3DC277CE7</LearningStandardItemRefId>
    </RelatedLearningStandardItems>
  </LearningStandardItem>
</LearningStandards>

redpajama_set_name: RedPajamaGithub


text:
var config = require('./config'),
  nestApi = require('./lib/nest'),
  nest = new nestApi(config);

nest.login()
	.then(nest.cameras())
	.then(function(obj) {
		console.log(obj);
		//console.log(JSON.parse(obj,null,4));
	})
	.catch(function(err) {
		console.log('there has been an error', err);
	});

// nest.login(config.token)
//   .then(nest.cameras)
//   .then(console.log.bind(console))
//   .catch(console.log.bind(console));


text:
一个完整的例子:

```js
var db = window.openDatabase('todo', '0.0.9', 'todo', 2 * 1024 * 1024);
db.transaction(
    function(transaction) {
      transaction.executeSql('CREATE TABLE IF NOT EXISTS CONF (k unique, v)');
      transaction.executeSql('INSERT INTO CONF (k, v) VALUES (?, ?)', ['msg', 'ok'],
          function(t, result) {
            console.log('result', result);
          },
          function(t, error) {
            console.log(error);
          }
      );
    },
    function() {
      console.log('error');
    },
    function() {
      console.log('success');
    }
);
```

DevTools 中可以看到类似的变化:

<img src="http://gtms03.alicdn.com/tps/i3/TB1fGgUJVXXXXchXXXXKUPqZpXX-1494-276.png" width="700">

由于 W3C 停止了对 Web SQL Database 规范的继续维护, MDN 上已经找不到 API 定义了, 不过仍然可以通过 [W3C 文档](https://dev.w3.org/html5/webdatabase/#sql) 查看到原始 API 定义。

定义 - `window.openDatabase`

```
[Supplemental, NoInterfaceObject]
interface WindowDatabase {
  Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
};
Window implements WindowDatabase;

[Callback=FunctionOnly, NoInterfaceObject]
interface DatabaseCallback {
  void handleEvent(in Database database);
};
```

定义 - `db.transaction(function callbakc(){}, function error(){}, function success(){})`

```
interface Database {
  void transaction(in SQLTransactionCallback callback, in optional SQLTransactionErrorCallback errorCallback, in optional SQLVoidCallback successCallback);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface SQLVoidCallback {
  void handleEvent();
};

[Callback=FunctionOnly, NoInterfaceObject]
interface SQLTransactionCallback {
  void handleEvent(in SQLTransaction transaction);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface SQLTransactionErrorCallback {
  void handleEvent(in SQLError error);
};
```

定义 - `db.executeSql(function(){}, [], function success(){}, function error(){})`

```
typedef sequence<any> ObjectArray;

interface SQLTransaction {
  void executeSql(in DOMString sqlStatement, in optional ObjectArray arguments, in optional SQLStatementCallback callback, in optional SQLStatementErrorCallback errorCallback);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface SQLStatementCallback {
  void handleEvent(in SQLTransaction transaction, in SQLResultSet resultSet);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface SQLStatementErrorCallback {
  boolean handleEvent(in SQLTransaction transaction, in SQLError error);
};

interface SQLResultSet {
  readonly attribute long insertId;
  readonly attribute long rowsAffected;
  readonly attribute SQLResultSetRowList rows;
};
```

## 改造 TodoMVC

详见[代码](https://github.com/luics/web-dev/blob/master/examples/data/TodoMVC-websql.html)


text:
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<meta http-equiv="refresh" content="1">
<title>httprefresh</title>
</head><body>
Testing httprefresh
</body></html>


text:
package org.apache.spark.sql.hive.client

import java.io.{File, PrintStream}
import java.util.Locale

import scala.collection.JavaConverters._
import scala.collection.mutable.ArrayBuffer

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.Path
import org.apache.hadoop.hive.conf.HiveConf
import org.apache.hadoop.hive.metastore.{TableType => HiveTableType}
import org.apache.hadoop.hive.metastore.api.{Database => HiveDatabase, FieldSchema, Order}
import org.apache.hadoop.hive.metastore.api.{SerDeInfo, StorageDescriptor}
import org.apache.hadoop.hive.ql.Driver
import org.apache.hadoop.hive.ql.metadata.{Hive, Partition => HivePartition, Table => HiveTable}
import org.apache.hadoop.hive.ql.parse.BaseSemanticAnalyzer.HIVE_COLUMN_ORDER_ASC
import org.apache.hadoop.hive.ql.processors._
import org.apache.hadoop.hive.ql.session.SessionState
import org.apache.hadoop.security.UserGroupInformation

import org.apache.spark.{SparkConf, SparkException}
import org.apache.spark.internal.Logging
import org.apache.spark.metrics.source.HiveCatalogMetrics
import org.apache.spark.sql.AnalysisException
import org.apache.spark.sql.catalyst.TableIdentifier
import org.apache.spark.sql.catalyst.analysis.{NoSuchDatabaseException, NoSuchPartitionException}
import org.apache.spark.sql.catalyst.catalog._
import org.apache.spark.sql.catalyst.catalog.CatalogTypes.TablePartitionSpec
import org.apache.spark.sql.catalyst.expressions.Expression
import org.apache.spark.sql.catalyst.parser.{CatalystSqlParser, ParseException}
import org.apache.spark.sql.execution.QueryExecutionException
import org.apache.spark.sql.execution.command.DDLUtils
import org.apache.spark.sql.hive.client.HiveClientImpl._
import org.apache.spark.sql.types._
import org.apache.spark.util.{CircularBuffer, Utils}

/**
 * A class that wraps the HiveClient and converts its responses to externally visible classes.
 * Note that this class is typically loaded with an internal classloader for each instantiation,
 * allowing it to interact directly with a specific isolated version of Hive.  Loading this class
 * with the isolated classloader however will result in it only being visible as a [[HiveClient]],
 * not a [[HiveClientImpl]].
 *
 * This class needs to interact with multiple versions of Hive, but will always be compiled with
 * the 'native', execution version of Hive.  Therefore, any places where hive breaks compatibility
 * must use reflection after matching on `version`.
 *
 * Every HiveClientImpl creates an internal HiveConf object. This object is using the given
 * `hadoopConf` as the base. All options set in the `sparkConf` will be applied to the HiveConf
 * object and overrides any exiting options. Then, options in extraConfig will be applied
 * to the HiveConf object and overrides any existing options.
 *
 * @param version the version of hive used when pick function calls that are not compatible.
 * @param sparkConf all configuration options set in SparkConf.
 * @param hadoopConf the base Configuration object used by the HiveConf created inside
 *                   this HiveClientImpl.
 * @param extraConfig a collection of configuration options that will be added to the
 *                hive conf before opening the hive client.
 * @param initClassLoader the classloader used when creating the `state` field of
 *                        this [[HiveClientImpl]].
 */
private[hive] class HiveClientImpl(
    override val version: HiveVersion,
    sparkConf: SparkConf,
    hadoopConf: Configuration,
    extraConfig: Map[String, String],
    initClassLoader: ClassLoader,
    val clientLoader: IsolatedClientLoader)
  extends HiveClient
  with Logging {

  // Circular buffer to hold what hive prints to STDOUT and ERR.  Only printed when failures occur.
  private val outputBuffer = new CircularBuffer()

  private val shim = version match {
    case hive.v12 => new Shim_v0_12()
    case hive.v13 => new Shim_v0_13()
    case hive.v14 => new Shim_v0_14()
    case hive.v1_0 => new Shim_v1_0()
    case hive.v1_1 => new Shim_v1_1()
    case hive.v1_2 => new Shim_v1_2()
    case hive.v2_0 => new Shim_v2_0()
    case hive.v2_1 => new Shim_v2_1()
  }

  // Create an internal session state for this HiveClientImpl.
  val state: SessionState = {
    val original = Thread.currentThread().getContextClassLoader
    // Switch to the initClassLoader.
    Thread.currentThread().setContextClassLoader(initClassLoader)

    // Set up kerberos credentials for UserGroupInformation.loginUser within
    // current class loader
    if (sparkConf.contains("spark.yarn.principal") && sparkConf.contains("spark.yarn.keytab")) {
      val principalName = sparkConf.get("spark.yarn.principal")
      val keytabFileName = sparkConf.get("spark.yarn.keytab")
      if (!new File(keytabFileName).exists()) {
        throw new SparkException(s"Keytab file: ${keytabFileName}" +
          " specified in spark.yarn.keytab does not exist")
      } else {
        logInfo("Attempting to login to Kerberos" +
          s" using principal: ${principalName} and keytab: ${keytabFileName}")
        UserGroupInformation.loginUserFromKeytab(principalName, keytabFileName)
      }
    }

    def isCliSessionState(state: SessionState): Boolean = {
      var temp: Class[_] = if (state != null) state.getClass else null
      var found = false
      while (temp != null && !found) {
        found = temp.getName == "org.apache.hadoop.hive.cli.CliSessionState"
        temp = temp.getSuperclass
      }
      found
    }

    val ret = try {
      // originState will be created if not exists, will never be null
      val originalState = SessionState.get()
      if (isCliSessionState(originalState)) {
        // In `SparkSQLCLIDriver`, we have already started a `CliSessionState`,
        // which contains information like configurations from command line. Later
        // we call `SparkSQLEnv.init()` there, which would run into this part again.
        // so we should keep `conf` and reuse the existing instance of `CliSessionState`.
        originalState
      } else {
        val hiveConf = new HiveConf(classOf[SessionState])
        // 1: we set all confs in the hadoopConf to this hiveConf.
        // This hadoopConf contains user settings in Hadoop's core-site.xml file
        // and Hive's hive-site.xml file. Note, we load hive-site.xml file manually in
        // SharedState and put settings in this hadoopConf instead of relying on HiveConf
        // to load user settings. Otherwise, HiveConf's initialize method will override
        // settings in the hadoopConf. This issue only shows up when spark.sql.hive.metastore.jars
        // is not set to builtin. When spark.sql.hive.metastore.jars is builtin, the classpath
        // has hive-site.xml. So, HiveConf will use that to override its default values.
        hadoopConf.iterator().asScala.foreach { entry =>
          val key = entry.getKey
          val value = entry.getValue
          if (key.toLowerCase(Locale.ROOT).contains("password")) {
            logDebug(s"Applying Hadoop and Hive config to Hive Conf: $key=xxx")
          } else {
            logDebug(s"Applying Hadoop and Hive config to Hive Conf: $key=$value")
          }
          hiveConf.set(key, value)
        }
        // HiveConf is a Hadoop Configuration, which has a field of classLoader and
        // the initial value will be the current thread's context class loader
        // (i.e. initClassLoader at here).
        // We call initialConf.setClassLoader(initClassLoader) at here to make
        // this action explicit.
        hiveConf.setClassLoader(initClassLoader)
        // 2: we set all spark confs to this hiveConf.
        sparkConf.getAll.foreach { case (k, v) =>
          if (k.toLowerCase(Locale.ROOT).contains("password")) {
            logDebug(s"Applying Spark config to Hive Conf: $k=xxx")
          } else {
            logDebug(s"Applying Spark config to Hive Conf: $k=$v")
          }
          hiveConf.set(k, v)
        }
        // 3: we set all entries in config to this hiveConf.
        extraConfig.foreach { case (k, v) =>
          if (k.toLowerCase(Locale.ROOT).contains("password")) {
            logDebug(s"Applying extra config to HiveConf: $k=xxx")
          } else {
            logDebug(s"Applying extra config to HiveConf: $k=$v")
          }
          hiveConf.set(k, v)
        }
        val state = new SessionState(hiveConf)
        if (clientLoader.cachedHive != null) {
          Hive.set(clientLoader.cachedHive.asInstanceOf[Hive])
        }
        SessionState.start(state)
        state.out = new PrintStream(outputBuffer, true, "UTF-8")
        state.err = new PrintStream(outputBuffer, true, "UTF-8")
        state
      }
    } finally {
      Thread.currentThread().setContextClassLoader(original)
    }
    ret
  }

  // Log the default warehouse location.
  logInfo(
    s"Warehouse location for Hive client " +
      s"(version ${version.fullVersion}) is ${conf.get("hive.metastore.warehouse.dir")}")

  /** Returns the configuration for the current session. */
  def conf: HiveConf = state.getConf

  private val userName = state.getAuthenticator.getUserName

  override def getConf(key: String, defaultValue: String): String = {
    conf.get(key, defaultValue)
  }

  // We use hive's conf for compatibility.
  private val retryLimit = conf.getIntVar(HiveConf.ConfVars.METASTORETHRIFTFAILURERETRIES)
  private val retryDelayMillis = shim.getMetastoreClientConnectRetryDelayMillis(conf)

  /**
   * Runs `f` with multiple retries in case the hive metastore is temporarily unreachable.
   */
  private def retryLocked[A](f: => A): A = clientLoader.synchronized {
    // Hive sometimes retries internally, so set a deadline to avoid compounding delays.
    val deadline = System.nanoTime + (retryLimit * retryDelayMillis * 1e6).toLong
    var numTries = 0
    var caughtException: Exception = null
    do {
      numTries += 1
      try {
        return f
      } catch {
        case e: Exception if causedByThrift(e) =>
          caughtException = e
          logWarning(
            "HiveClient got thrift exception, destroying client and retrying " +
              s"(${retryLimit - numTries} tries remaining)", e)
          clientLoader.cachedHive = null
          Thread.sleep(retryDelayMillis)
      }
    } while (numTries <= retryLimit && System.nanoTime < deadline)
    if (System.nanoTime > deadline) {
      logWarning("Deadline exceeded")
    }
    throw caughtException
  }

  private def causedByThrift(e: Throwable): Boolean = {
    var target = e
    while (target != null) {
      val msg = target.getMessage()
      if (msg != null && msg.matches("(?s).*(TApplication|TProtocol|TTransport)Exception.*")) {
        return true
      }
      target = target.getCause()
    }
    false
  }

  private def client: Hive = {
    if (clientLoader.cachedHive != null) {
      clientLoader.cachedHive.asInstanceOf[Hive]
    } else {
      val c = Hive.get(conf)
      clientLoader.cachedHive = c
      c
    }
  }

  /**
   * Runs `f` with ThreadLocal session state and classloaders configured for this version of hive.
   */
  def withHiveState[A](f: => A): A = retryLocked {
    val original = Thread.currentThread().getContextClassLoader
    val originalConfLoader = state.getConf.getClassLoader
    // The classloader in clientLoader could be changed after addJar, always use the latest
    // classloader. We explicitly set the context class loader since "conf.setClassLoader" does
    // not do that, and the Hive client libraries may need to load classes defined by the client's
    // class loader.
    Thread.currentThread().setContextClassLoader(clientLoader.classLoader)
    state.getConf.setClassLoader(clientLoader.classLoader)
    // Set the thread local metastore client to the client associated with this HiveClientImpl.
    Hive.set(client)
    // Replace conf in the thread local Hive with current conf
    Hive.get(conf)
    // setCurrentSessionState will use the classLoader associated
    // with the HiveConf in `state` to override the context class loader of the current
    // thread.
    shim.setCurrentSessionState(state)
    val ret = try f finally {
      state.getConf.setClassLoader(originalConfLoader)
      Thread.currentThread().setContextClassLoader(original)
      HiveCatalogMetrics.incrementHiveClientCalls(1)
    }
    ret
  }

  def setOut(stream: PrintStream): Unit = withHiveState {
    state.out = stream
  }

  def setInfo(stream: PrintStream): Unit = withHiveState {
    state.info = stream
  }

  def setError(stream: PrintStream): Unit = withHiveState {
    state.err = stream
  }

  override def setCurrentDatabase(databaseName: String): Unit = withHiveState {
    if (databaseExists(databaseName)) {
      state.setCurrentDatabase(databaseName)
    } else {
      throw new NoSuchDatabaseException(databaseName)
    }
  }

  override def createDatabase(
      database: CatalogDatabase,
      ignoreIfExists: Boolean): Unit = withHiveState {
    client.createDatabase(
      new HiveDatabase(
        database.name,
        database.description,
        CatalogUtils.URIToString(database.locationUri),
        Option(database.properties).map(_.asJava).orNull),
        ignoreIfExists)
  }

  override def dropDatabase(
      name: String,
      ignoreIfNotExists: Boolean,
      cascade: Boolean): Unit = withHiveState {
    client.dropDatabase(name, true, ignoreIfNotExists, cascade)
  }

  override def alterDatabase(database: CatalogDatabase): Unit = withHiveState {
    client.alterDatabase(
      database.name,
      new HiveDatabase(
        database.name,
        database.description,
        CatalogUtils.URIToString(database.locationUri),
        Option(database.properties).map(_.asJava).orNull))
  }

  override def getDatabase(dbName: String): CatalogDatabase = withHiveState {
    Option(client.getDatabase(dbName)).map { d =>
      CatalogDatabase(
        name = d.getName,
        description = d.getDescription,
        locationUri = CatalogUtils.stringToURI(d.getLocationUri),
        properties = Option(d.getParameters).map(_.asScala.toMap).orNull)
    }.getOrElse(throw new NoSuchDatabaseException(dbName))
  }

  override def databaseExists(dbName: String): Boolean = withHiveState {
    client.databaseExists(dbName)
  }

  override def listDatabases(pattern: String): Seq[String] = withHiveState {
    client.getDatabasesByPattern(pattern).asScala
  }

  override def tableExists(dbName: String, tableName: String): Boolean = withHiveState {
    Option(client.getTable(dbName, tableName, false /* do not throw exception */)).nonEmpty
  }

  override def getTableOption(
      dbName: String,
      tableName: String): Option[CatalogTable] = withHiveState {
    logDebug(s"Looking up $dbName.$tableName")
    Option(client.getTable(dbName, tableName, false)).map { h =>
      // Note: Hive separates partition columns and the schema, but for us the
      // partition columns are part of the schema
      val cols = h.getCols.asScala.map(fromHiveColumn)
      val partCols = h.getPartCols.asScala.map(fromHiveColumn)
      val schema = StructType(cols ++ partCols)

      val bucketSpec = if (h.getNumBuckets > 0) {
        val sortColumnOrders = h.getSortCols.asScala
        // Currently Spark only supports columns to be sorted in ascending order
        // but Hive can support both ascending and descending order. If all the columns
        // are sorted in ascending order, only then propagate the sortedness information
        // to downstream processing / optimizations in Spark
        // TODO: In future we can have Spark support columns sorted in descending order
        val allAscendingSorted = sortColumnOrders.forall(_.getOrder == HIVE_COLUMN_ORDER_ASC)

        val sortColumnNames = if (allAscendingSorted) {
          sortColumnOrders.map(_.getCol)
        } else {
          Seq()
        }
        Option(BucketSpec(h.getNumBuckets, h.getBucketCols.asScala, sortColumnNames))
      } else {
        None
      }

      // Skew spec and storage handler can't be mapped to CatalogTable (yet)
      val unsupportedFeatures = ArrayBuffer.empty[String]

      if (!h.getSkewedColNames.isEmpty) {
        unsupportedFeatures += "skewed columns"
      }

      if (h.getStorageHandler != null) {
        unsupportedFeatures += "storage handler"
      }

      if (h.getTableType == HiveTableType.VIRTUAL_VIEW && partCols.nonEmpty) {
        unsupportedFeatures += "partitioned view"
      }

      val properties = Option(h.getParameters).map(_.asScala.toMap).orNull

      CatalogTable(
        identifier = TableIdentifier(h.getTableName, Option(h.getDbName)),
        tableType = h.getTableType match {
          case HiveTableType.EXTERNAL_TABLE => CatalogTableType.EXTERNAL
          case HiveTableType.MANAGED_TABLE => CatalogTableType.MANAGED
          case HiveTableType.VIRTUAL_VIEW => CatalogTableType.VIEW
          case HiveTableType.INDEX_TABLE =>
            throw new AnalysisException("Hive index table is not supported.")
        },
        schema = schema,
        partitionColumnNames = partCols.map(_.name),
        // If the table is written by Spark, we will put bucketing information in table properties,
        // and will always overwrite the bucket spec in hive metastore by the bucketing information
        // in table properties. This means, if we have bucket spec in both hive metastore and
        // table properties, we will trust the one in table properties.
        bucketSpec = bucketSpec,
        owner = h.getOwner,
        createTime = h.getTTable.getCreateTime.toLong * 1000,
        lastAccessTime = h.getLastAccessTime.toLong * 1000,
        storage = CatalogStorageFormat(
          locationUri = shim.getDataLocation(h).map(CatalogUtils.stringToURI),
          // To avoid ClassNotFound exception, we try our best to not get the format class, but get
          // the class name directly. However, for non-native tables, there is no interface to get
          // the format class name, so we may still throw ClassNotFound in this case.
          inputFormat = Option(h.getTTable.getSd.getInputFormat).orElse {
            Option(h.getStorageHandler).map(_.getInputFormatClass.getName)
          },
          outputFormat = Option(h.getTTable.getSd.getOutputFormat).orElse {
            Option(h.getStorageHandler).map(_.getOutputFormatClass.getName)
          },
          serde = Option(h.getSerializationLib),
          compressed = h.getTTable.getSd.isCompressed,
          properties = Option(h.getTTable.getSd.getSerdeInfo.getParameters)
            .map(_.asScala.toMap).orNull
        ),
        // For EXTERNAL_TABLE, the table properties has a particular field "EXTERNAL". This is added
        // in the function toHiveTable.
        properties = properties.filter(kv => kv._1 != "comment" && kv._1 != "EXTERNAL"),
        comment = properties.get("comment"),
        // In older versions of Spark(before 2.2.0), we expand the view original text and store
        // that into `viewExpandedText`, and that should be used in view resolution. So we get
        // `viewExpandedText` instead of `viewOriginalText` for viewText here.
        viewText = Option(h.getViewExpandedText),
        unsupportedFeatures = unsupportedFeatures)
    }
  }

  override def createTable(table: CatalogTable, ignoreIfExists: Boolean): Unit = withHiveState {
    client.createTable(toHiveTable(table, Some(userName)), ignoreIfExists)
  }

  override def dropTable(
      dbName: String,
      tableName: String,
      ignoreIfNotExists: Boolean,
      purge: Boolean): Unit = withHiveState {
    shim.dropTable(client, dbName, tableName, true, ignoreIfNotExists, purge)
  }

  override def alterTable(tableName: String, table: CatalogTable): Unit = withHiveState {
    val hiveTable = toHiveTable(table, Some(userName))
    // Do not use `table.qualifiedName` here because this may be a rename
    val qualifiedTableName = s"${table.database}.$tableName"
    shim.alterTable(client, qualifiedTableName, hiveTable)
  }

  override def createPartitions(
      db: String,
      table: String,
      parts: Seq[CatalogTablePartition],
      ignoreIfExists: Boolean): Unit = withHiveState {
    shim.createPartitions(client, db, table, parts, ignoreIfExists)
  }

  override def dropPartitions(
      db: String,
      table: String,
      specs: Seq[TablePartitionSpec],
      ignoreIfNotExists: Boolean,
      purge: Boolean,
      retainData: Boolean): Unit = withHiveState {
    // TODO: figure out how to drop multiple partitions in one call
    val hiveTable = client.getTable(db, table, true /* throw exception */)
    // do the check at first and collect all the matching partitions
    val matchingParts =
      specs.flatMap { s =>
        assert(s.values.forall(_.nonEmpty), s"partition spec '$s' is invalid")
        // The provided spec here can be a partial spec, i.e. it will match all partitions
        // whose specs are supersets of this partial spec. E.g. If a table has partitions
        // (b='1', c='1') and (b='1', c='2'), a partial spec of (b='1') will match both.
        val parts = client.getPartitions(hiveTable, s.asJava).asScala
        if (parts.isEmpty && !ignoreIfNotExists) {
          throw new AnalysisException(
            s"No partition is dropped. One partition spec '$s' does not exist in table '$table' " +
            s"database '$db'")
        }
        parts.map(_.getValues)
      }.distinct
    var droppedParts = ArrayBuffer.empty[java.util.List[String]]
    matchingParts.foreach { partition =>
      try {
        shim.dropPartition(client, db, table, partition, !retainData, purge)
      } catch {
        case e: Exception =>
          val remainingParts = matchingParts.toBuffer -- droppedParts
          logError(
            s"""
               |======================
               |Attempt to drop the partition specs in table '$table' database '$db':
               |${specs.mkString("\n")}
               |In this attempt, the following partitions have been dropped successfully:
               |${droppedParts.mkString("\n")}
               |The remaining partitions have not been dropped:
               |${remainingParts.mkString("\n")}
               |======================
             """.stripMargin)
          throw e
      }
      droppedParts += partition
    }
  }

  override def renamePartitions(
      db: String,
      table: String,
      specs: Seq[TablePartitionSpec],
      newSpecs: Seq[TablePartitionSpec]): Unit = withHiveState {
    require(specs.size == newSpecs.size, "number of old and new partition specs differ")
    val catalogTable = getTable(db, table)
    val hiveTable = toHiveTable(catalogTable, Some(userName))
    specs.zip(newSpecs).foreach { case (oldSpec, newSpec) =>
      val hivePart = getPartitionOption(catalogTable, oldSpec)
        .map { p => toHivePartition(p.copy(spec = newSpec), hiveTable) }
        .getOrElse { throw new NoSuchPartitionException(db, table, oldSpec) }
      client.renamePartition(hiveTable, oldSpec.asJava, hivePart)
    }
  }

  override def alterPartitions(
      db: String,
      table: String,
      newParts: Seq[CatalogTablePartition]): Unit = withHiveState {
    val hiveTable = toHiveTable(getTable(db, table), Some(userName))
    shim.alterPartitions(client, table, newParts.map { p => toHivePartition(p, hiveTable) }.asJava)
  }

  /**
   * Returns the partition names for the given table that match the supplied partition spec.
   * If no partition spec is specified, all partitions are returned.
   *
   * The returned sequence is sorted as strings.
   */
  override def getPartitionNames(
      table: CatalogTable,
      partialSpec: Option[TablePartitionSpec] = None): Seq[String] = withHiveState {
    val hivePartitionNames =
      partialSpec match {
        case None =>
          // -1 for result limit means "no limit/return all"
          client.getPartitionNames(table.database, table.identifier.table, -1)
        case Some(s) =>
          assert(s.values.forall(_.nonEmpty), s"partition spec '$s' is invalid")
          client.getPartitionNames(table.database, table.identifier.table, s.asJava, -1)
      }
    hivePartitionNames.asScala.sorted
  }

  override def getPartitionOption(
      table: CatalogTable,
      spec: TablePartitionSpec): Option[CatalogTablePartition] = withHiveState {
    val hiveTable = toHiveTable(table, Some(userName))
    val hivePartition = client.getPartition(hiveTable, spec.asJava, false)
    Option(hivePartition).map(fromHivePartition)
  }

  /**
   * Returns the partitions for the given table that match the supplied partition spec.
   * If no partition spec is specified, all partitions are returned.
   */
  override def getPartitions(
      table: CatalogTable,
      spec: Option[TablePartitionSpec]): Seq[CatalogTablePartition] = withHiveState {
    val hiveTable = toHiveTable(table, Some(userName))
    val parts = spec match {
      case None => shim.getAllPartitions(client, hiveTable).map(fromHivePartition)
      case Some(s) =>
        assert(s.values.forall(_.nonEmpty), s"partition spec '$s' is invalid")
        client.getPartitions(hiveTable, s.asJava).asScala.map(fromHivePartition)
    }
    HiveCatalogMetrics.incrementFetchedPartitions(parts.length)
    parts
  }

  override def getPartitionsByFilter(
      table: CatalogTable,
      predicates: Seq[Expression]): Seq[CatalogTablePartition] = withHiveState {
    val hiveTable = toHiveTable(table, Some(userName))
    val parts = shim.getPartitionsByFilter(client, hiveTable, predicates).map(fromHivePartition)
    HiveCatalogMetrics.incrementFetchedPartitions(parts.length)
    parts
  }

  override def listTables(dbName: String): Seq[String] = withHiveState {
    client.getAllTables(dbName).asScala
  }

  override def listTables(dbName: String, pattern: String): Seq[String] = withHiveState {
    client.getTablesByPattern(dbName, pattern).asScala
  }

  /**
   * Runs the specified SQL query using Hive.
   */
  override def runSqlHive(sql: String): Seq[String] = {
    val maxResults = 100000
    val results = runHive(sql, maxResults)
    // It is very confusing when you only get back some of the results...
    if (results.size == maxResults) sys.error("RESULTS POSSIBLY TRUNCATED")
    results
  }

  /**
   * Execute the command using Hive and return the results as a sequence. Each element
   * in the sequence is one row.
   */
  protected def runHive(cmd: String, maxRows: Int = 1000): Seq[String] = withHiveState {
    logDebug(s"Running hiveql '$cmd'")
    if (cmd.toLowerCase(Locale.ROOT).startsWith("set")) { logDebug(s"Changing config: $cmd") }
    try {
      val cmd_trimmed: String = cmd.trim()
      val tokens: Array[String] = cmd_trimmed.split("\\s+")
      // The remainder of the command.
      val cmd_1: String = cmd_trimmed.substring(tokens(0).length()).trim()
      val proc = shim.getCommandProcessor(tokens(0), conf)
      proc match {
        case driver: Driver =>
          val response: CommandProcessorResponse = driver.run(cmd)
          // Throw an exception if there is an error in query processing.
          if (response.getResponseCode != 0) {
            driver.close()
            CommandProcessorFactory.clean(conf)
            throw new QueryExecutionException(response.getErrorMessage)
          }
          driver.setMaxRows(maxRows)

          val results = shim.getDriverResults(driver)
          driver.close()
          CommandProcessorFactory.clean(conf)
          results

        case _ =>
          if (state.out != null) {
            // scalastyle:off println
            state.out.println(tokens(0) + " " + cmd_1)
            // scalastyle:on println
          }
          Seq(proc.run(cmd_1).getResponseCode.toString)
      }
    } catch {
      case e: Exception =>
        logError(
          s"""
            |======================
            |HIVE FAILURE OUTPUT
            |======================
            |${outputBuffer.toString}
            |======================
            |END HIVE FAILURE OUTPUT
            |======================
          """.stripMargin)
        throw e
    }
  }

  def loadPartition(
      loadPath: String,
      dbName: String,
      tableName: String,
      partSpec: java.util.LinkedHashMap[String, String],
      replace: Boolean,
      inheritTableSpecs: Boolean,
      isSrcLocal: Boolean): Unit = withHiveState {
    val hiveTable = client.getTable(dbName, tableName, true /* throw exception */)
    shim.loadPartition(
      client,
      new Path(loadPath), // TODO: Use URI
      s"$dbName.$tableName",
      partSpec,
      replace,
      inheritTableSpecs,
      isSkewedStoreAsSubdir = hiveTable.isStoredAsSubDirectories,
      isSrcLocal = isSrcLocal)
  }

  def loadTable(
      loadPath: String, // TODO URI
      tableName: String,
      replace: Boolean,
      isSrcLocal: Boolean): Unit = withHiveState {
    shim.loadTable(
      client,
      new Path(loadPath),
      tableName,
      replace,
      isSrcLocal)
  }

  def loadDynamicPartitions(
      loadPath: String,
      dbName: String,
      tableName: String,
      partSpec: java.util.LinkedHashMap[String, String],
      replace: Boolean,
      numDP: Int): Unit = withHiveState {
    val hiveTable = client.getTable(dbName, tableName, true /* throw exception */)
    shim.loadDynamicPartitions(
      client,
      new Path(loadPath),
      s"$dbName.$tableName",
      partSpec,
      replace,
      numDP,
      listBucketingEnabled = hiveTable.isStoredAsSubDirectories)
  }

  override def createFunction(db: String, func: CatalogFunction): Unit = withHiveState {
    shim.createFunction(client, db, func)
  }

  override def dropFunction(db: String, name: String): Unit = withHiveState {
    shim.dropFunction(client, db, name)
  }

  override def renameFunction(db: String, oldName: String, newName: String): Unit = withHiveState {
    shim.renameFunction(client, db, oldName, newName)
  }

  override def alterFunction(db: String, func: CatalogFunction): Unit = withHiveState {
    shim.alterFunction(client, db, func)
  }

  override def getFunctionOption(
      db: String, name: String): Option[CatalogFunction] = withHiveState {
    shim.getFunctionOption(client, db, name)
  }

  override def listFunctions(db: String, pattern: String): Seq[String] = withHiveState {
    shim.listFunctions(client, db, pattern)
  }

  def addJar(path: String): Unit = {
    val uri = new Path(path).toUri
    val jarURL = if (uri.getScheme == null) {
      // `path` is a local file path without a URL scheme
      new File(path).toURI.toURL
    } else {
      // `path` is a URL with a scheme
      uri.toURL
    }
    clientLoader.addJar(jarURL)
    runSqlHive(s"ADD JAR $path")
  }

  def newSession(): HiveClientImpl = {
    clientLoader.createClient().asInstanceOf[HiveClientImpl]
  }

  def reset(): Unit = withHiveState {
    client.getAllTables("default").asScala.foreach { t =>
        logDebug(s"Deleting table $t")
        val table = client.getTable("default", t)
        client.getIndexes("default", t, 255).asScala.foreach { index =>
          shim.dropIndex(client, "default", t, index.getIndexName)
        }
        if (!table.isIndexTable) {
          client.dropTable("default", t)
        }
      }
      client.getAllDatabases.asScala.filterNot(_ == "default").foreach { db =>
        logDebug(s"Dropping Database: $db")
        client.dropDatabase(db, true, false, true)
      }
  }
}

private[hive] object HiveClientImpl {
  /** Converts the native StructField to Hive's FieldSchema. */
  def toHiveColumn(c: StructField): FieldSchema = {
    val typeString = if (c.metadata.contains(HIVE_TYPE_STRING)) {
      c.metadata.getString(HIVE_TYPE_STRING)
    } else {
      c.dataType.catalogString
    }
    new FieldSchema(c.name, typeString, c.getComment().orNull)
  }

  /** Builds the native StructField from Hive's FieldSchema. */
  def fromHiveColumn(hc: FieldSchema): StructField = {
    val columnType = try {
      CatalystSqlParser.parseDataType(hc.getType)
    } catch {
      case e: ParseException =>
        throw new SparkException("Cannot recognize hive type string: " + hc.getType, e)
    }

    val metadata = new MetadataBuilder().putString(HIVE_TYPE_STRING, hc.getType).build()
    val field = StructField(
      name = hc.getName,
      dataType = columnType,
      nullable = true,
      metadata = metadata)
    Option(hc.getComment).map(field.withComment).getOrElse(field)
  }

  private def toInputFormat(name: String) =
    Utils.classForName(name).asInstanceOf[Class[_ <: org.apache.hadoop.mapred.InputFormat[_, _]]]

  private def toOutputFormat(name: String) =
    Utils.classForName(name)
      .asInstanceOf[Class[_ <: org.apache.hadoop.hive.ql.io.HiveOutputFormat[_, _]]]

  /**
   * Converts the native table metadata representation format CatalogTable to Hive's Table.
   */
  def toHiveTable(table: CatalogTable, userName: Option[String] = None): HiveTable = {
    val hiveTable = new HiveTable(table.database, table.identifier.table)
    // For EXTERNAL_TABLE, we also need to set EXTERNAL field in the table properties.
    // Otherwise, Hive metastore will change the table to a MANAGED_TABLE.
    // (metastore/src/java/org/apache/hadoop/hive/metastore/ObjectStore.java#L1095-L1105)
    hiveTable.setTableType(table.tableType match {
      case CatalogTableType.EXTERNAL =>
        hiveTable.setProperty("EXTERNAL", "TRUE")
        HiveTableType.EXTERNAL_TABLE
      case CatalogTableType.MANAGED =>
        HiveTableType.MANAGED_TABLE
      case CatalogTableType.VIEW => HiveTableType.VIRTUAL_VIEW
    })
    // Note: In Hive the schema and partition columns must be disjoint sets
    val (partCols, schema) = table.schema.map(toHiveColumn).partition { c =>
      table.partitionColumnNames.contains(c.getName)
    }
    // after SPARK-19279, it is not allowed to create a hive table with an empty schema,
    // so here we should not add a default col schema
    if (schema.isEmpty && DDLUtils.isDatasourceTable(table)) {
      // This is a hack to preserve existing behavior. Before Spark 2.0, we do not
      // set a default serde here (this was done in Hive), and so if the user provides
      // an empty schema Hive would automatically populate the schema with a single
      // field "col". However, after SPARK-14388, we set the default serde to
      // LazySimpleSerde so this implicit behavior no longer happens. Therefore,
      // we need to do it in Spark ourselves.
      hiveTable.setFields(
        Seq(new FieldSchema("col", "array<string>", "from deserializer")).asJava)
    } else {
      hiveTable.setFields(schema.asJava)
    }
    hiveTable.setPartCols(partCols.asJava)
    userName.foreach(hiveTable.setOwner)
    hiveTable.setCreateTime((table.createTime / 1000).toInt)
    hiveTable.setLastAccessTime((table.lastAccessTime / 1000).toInt)
    table.storage.locationUri.map(CatalogUtils.URIToString).foreach { loc =>
      hiveTable.getTTable.getSd.setLocation(loc)}
    table.storage.inputFormat.map(toInputFormat).foreach(hiveTable.setInputFormatClass)
    table.storage.outputFormat.map(toOutputFormat).foreach(hiveTable.setOutputFormatClass)
    hiveTable.setSerializationLib(
      table.storage.serde.getOrElse("org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe"))
    table.storage.properties.foreach { case (k, v) => hiveTable.setSerdeParam(k, v) }
    table.properties.foreach { case (k, v) => hiveTable.setProperty(k, v) }
    table.comment.foreach { c => hiveTable.setProperty("comment", c) }
    // Hive will expand the view text, so it needs 2 fields: viewOriginalText and viewExpandedText.
    // Since we don't expand the view text, but only add table properties, we map the `viewText` to
    // the both fields in hive table.
    table.viewText.foreach { t =>
      hiveTable.setViewOriginalText(t)
      hiveTable.setViewExpandedText(t)
    }

    table.bucketSpec match {
      case Some(bucketSpec) if DDLUtils.isHiveTable(table) =>
        hiveTable.setNumBuckets(bucketSpec.numBuckets)
        hiveTable.setBucketCols(bucketSpec.bucketColumnNames.toList.asJava)

        if (bucketSpec.sortColumnNames.nonEmpty) {
          hiveTable.setSortCols(
            bucketSpec.sortColumnNames
              .map(col => new Order(col, HIVE_COLUMN_ORDER_ASC))
              .toList
              .asJava
          )
        }
      case _ =>
    }

    hiveTable
  }

  /**
   * Converts the native partition metadata representation format CatalogTablePartition to
   * Hive's Partition.
   */
  def toHivePartition(
      p: CatalogTablePartition,
      ht: HiveTable): HivePartition = {
    val tpart = new org.apache.hadoop.hive.metastore.api.Partition
    val partValues = ht.getPartCols.asScala.map { hc =>
      p.spec.get(hc.getName).getOrElse {
        throw new IllegalArgumentException(
          s"Partition spec is missing a value for column '${hc.getName}': ${p.spec}")
      }
    }
    val storageDesc = new StorageDescriptor
    val serdeInfo = new SerDeInfo
    p.storage.locationUri.map(CatalogUtils.URIToString(_)).foreach(storageDesc.setLocation)
    p.storage.inputFormat.foreach(storageDesc.setInputFormat)
    p.storage.outputFormat.foreach(storageDesc.setOutputFormat)
    p.storage.serde.foreach(serdeInfo.setSerializationLib)
    serdeInfo.setParameters(p.storage.properties.asJava)
    storageDesc.setSerdeInfo(serdeInfo)
    tpart.setDbName(ht.getDbName)
    tpart.setTableName(ht.getTableName)
    tpart.setValues(partValues.asJava)
    tpart.setSd(storageDesc)
    new HivePartition(ht, tpart)
  }

  /**
   * Build the native partition metadata from Hive's Partition.
   */
  def fromHivePartition(hp: HivePartition): CatalogTablePartition = {
    val apiPartition = hp.getTPartition
    CatalogTablePartition(
      spec = Option(hp.getSpec).map(_.asScala.toMap).getOrElse(Map.empty),
      storage = CatalogStorageFormat(
        locationUri = Option(CatalogUtils.stringToURI(apiPartition.getSd.getLocation)),
        inputFormat = Option(apiPartition.getSd.getInputFormat),
        outputFormat = Option(apiPartition.getSd.getOutputFormat),
        serde = Option(apiPartition.getSd.getSerdeInfo.getSerializationLib),
        compressed = apiPartition.getSd.isCompressed,
        properties = Option(apiPartition.getSd.getSerdeInfo.getParameters)
          .map(_.asScala.toMap).orNull),
        parameters =
          if (hp.getParameters() != null) hp.getParameters().asScala.toMap else Map.empty)
  }
}


text:
package org.newdawn.slick.font.effects;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.util.Iterator;
import java.util.List;

/**
 * An effect that genrates a wobbly line around the outline of the text
 *
 * @author Jerry Huxtable
 * @author Nathan Sweet <misc@n4te.com>
 */
public class OutlineWobbleEffect extends OutlineEffect {
	/** How often the line wobbles */
	private float detail = 1;
	/** The amount of the line wobbles */
	private float amplitude = 1;

	/**
	 * Default constructor for injection
	 */
	public OutlineWobbleEffect () {
		setStroke(new WobbleStroke());
	}

	/**
	 * Gets the detail of the wobble effect.
	 *
	 * @return The detail of the wobble effect
	 */
	public float getDetail() {
		return detail;
	}

	/**
	 * Sets the detail of the wobble effect.
	 *
	 * @param detail The detail of the wobble effect
	 */
	public void setDetail(float detail) {
		this.detail = detail;
	}

	/**
	 * Gets the amplitude of the wobble effect.
	 *
	 * @return The amplitude of the wobble effect
	 */
	public float getAmplitude() {
		return amplitude;
	}

	/**
	 * Sets the amplitude of the wobble effect.
	 *
	 * @param amplitude The detail of the wobble effect
	 */
	public void setAmplitude(float amplitude) {
		this.amplitude = amplitude;
	}

	/**
	 * Create a new effect that generates a wobbly line around the text
	 *
	 * @param width The width of the line
	 * @param color The colour of the line
	 */
	public OutlineWobbleEffect (int width, Color color) {
		super(width, color);
	}

	/**
	 * @see org.newdawn.slick.font.effects.OutlineEffect#toString()
	 */
	public String toString() {
		return "Outline (Wobble)";
	}

	/**
	 * @see org.newdawn.slick.font.effects.OutlineEffect#getValues()
	 */
	public List getValues() {
		List values = super.getValues();
		values.remove(2); // Remove "Join".
		values.add(EffectUtil.floatValue("Detail", detail, 1, 50, "This setting controls how detailed the outline will be. "
			+ "Smaller numbers cause the outline to have more detail."));
		values.add(EffectUtil.floatValue("Amplitude", amplitude, 0.5f, 50, "This setting controls the amplitude of the outline."));
		return values;
	}

	/**
	 * @see org.newdawn.slick.font.effects.OutlineEffect#setValues(java.util.List)
	 */
	public void setValues(List values) {
		super.setValues(values);
		for (Iterator iter = values.iterator(); iter.hasNext();) {
			Value value = (Value)iter.next();
			if (value.getName().equals("Detail")) {
				detail = ((Float)value.getObject()).floatValue();
			} else if (value.getName().equals("Amplitude")) {
				amplitude = ((Float)value.getObject()).floatValue();
			}
		}
	}

	/**
	 * A stroke that generate a wobbly line
	 *
	 * @author Jerry Huxtable
	 * @author Nathan Sweet <misc@n4te.com>
	 */
	private class WobbleStroke implements Stroke {
		/** The flattening factor of the stroke */
		private static final float FLATNESS = 1;

		/**
		 * @see java.awt.Stroke#createStrokedShape(java.awt.Shape)
		 */
		public Shape createStrokedShape (Shape shape) {
			GeneralPath result = new GeneralPath();
			shape = new BasicStroke(getWidth(), BasicStroke.CAP_SQUARE, getJoin()).createStrokedShape(shape);
			PathIterator it = new FlatteningPathIterator(shape.getPathIterator(null), FLATNESS);
			float points[] = new float[6];
			float moveX = 0, moveY = 0;
			float lastX = 0, lastY = 0;
			float thisX = 0, thisY = 0;
			int type = 0;
			float next = 0;
			while (!it.isDone()) {
				type = it.currentSegment(points);
				switch (type) {
				case PathIterator.SEG_MOVETO:
					moveX = lastX = randomize(points[0]);
					moveY = lastY = randomize(points[1]);
					result.moveTo(moveX, moveY);
					next = 0;
					break;

				case PathIterator.SEG_CLOSE:
					points[0] = moveX;
					points[1] = moveY;
					// Fall into....

				case PathIterator.SEG_LINETO:
					thisX = randomize(points[0]);
					thisY = randomize(points[1]);
					float dx = thisX - lastX;
					float dy = thisY - lastY;
					float distance = (float)Math.sqrt(dx * dx + dy * dy);
					if (distance >= next) {
						float r = 1.0f / distance;
						while (distance >= next) {
							float x = lastX + next * dx * r;
							float y = lastY + next * dy * r;
							result.lineTo(randomize(x), randomize(y));
							next += detail;
						}
					}
					next -= distance;
					lastX = thisX;
					lastY = thisY;
					break;
				}
				it.next();
			}

			return result;
		}

		/**
		 * Get a random wobble factor
		 *
		 * @param x The position on the line
		 * @return The wobble factor
		 */
		private float randomize(float x) {
			return x + (float)Math.random() * amplitude * 2 - 1;
		}
	}
}


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.4"/>
<title>LUFA Library - DFU Class Bootloader: USB_Descriptor_DFU_Functional_t Struct Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>

<link href="navtree.css" rel="stylesheet" type="text/css"/>

<link href="doxygen.css" rel="stylesheet" type="text/css" />

LUFA Library - DFU Class Bootloader

Data Fields

USB_Descriptor_DFU_Functional_t Struct Reference

#include <Descriptors.h>

Data Fields

USB_Descriptor_Header_t 	Header

uint8_t 	Attributes

uint16_t 	DetachTimeout

uint16_t 	TransferSize

uint16_t 	DFUSpecification

Detailed Description

Type define for a DFU class function descriptor. This descriptor gives DFU class information to the host when read, indicating the DFU device's capabilities.

Field Documentation

          uint8_t USB_Descriptor_DFU_Functional_t::Attributes

DFU device attributes, a mask comprising of the ATTR_* macros listed in this source file

          uint16_t USB_Descriptor_DFU_Functional_t::DetachTimeout

Timeout in milliseconds between a USB_DETACH command being issued and the device detaching from the USB bus

          uint16_t USB_Descriptor_DFU_Functional_t::DFUSpecification

BCD packed DFU specification number this DFU device complies with

          USB_Descriptor_Header_t USB_Descriptor_DFU_Functional_t::Header

Standard descriptor header structure

          uint16_t USB_Descriptor_DFU_Functional_t::TransferSize

Maximum number of bytes the DFU device can accept from the host in a transaction

The documentation for this struct was generated from the following file:

Descriptors.h

USB_Descriptor_DFU_Functional_t

Generated by

     1.8.4


text:
class GURL;

namespace content {

// A virtual app URL identifying the browser itself. This should be used for
// a connection's |requestor_url| when connecting from browser code to apps that
// don't require a more specific request context.
CONTENT_EXPORT extern const char kBrowserMojoAppUrl[];

// This provides a way for arbitrary browser code to connect to Mojo apps. These
// objects are not thread-safe but may be constructed and used on any single
// thread.
class CONTENT_EXPORT MojoAppConnection {
 public:
  virtual ~MojoAppConnection() {}

  // Creates a new connection to the application at |url| using |requestor_url|
  // to identify the requestor upon connection. This may be called from any
  // thread.
  static scoped_ptr<MojoAppConnection> Create(const GURL& url,
                                              const GURL& requestor_url);

  // Connects to a service within the application.
  template <typename Interface>
  void GetInterface(mojo::InterfacePtr<Interface>* proxy) {
    GetInterface(Interface::Name_, mojo::GetProxy(proxy).PassMessagePipe());
  }

  virtual void GetInterface(const std::string& interface_name,
                            mojo::ScopedMessagePipeHandle handle) = 0;
};

}  // namespace content

#endif  // CONTENT_PUBLIC_BROWSER_MOJO_APP_CONNECTION_H_


text:
package com.aspose.cloud.sdk.pdf.model;

import com.aspose.cloud.sdk.common.BaseResponse;
import com.aspose.cloud.sdk.common.LinkModel;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;

public class AttachmentsResponse extends BaseResponse{
	@SerializedName("Attachments")
	public AttachmentsResult attachments;

	public class AttachmentsResult {
		public ArrayList<LinkModel> Links;
        public ArrayList<AttachmentDetails> List;
	}
}


text:
'use strict';
const { MongoClient } = require('../../src');
const chai = require('chai');
const sinon = require('sinon');
const dns = require('dns');

const expect = chai.expect;
chai.use(require('sinon-chai'));

function verifyKerberosAuthentication(client, done) {
  client
    .db('kerberos')
    .collection('test')
    .find()
    .toArray(function (err, docs) {
      let expectError;
      try {
        expect(err).to.not.exist;
        expect(docs).to.have.length(1);
        expect(docs[0].kerberos).to.be.true;
      } catch (e) {
        expectError = e;
      }
      client.close(e => done(expectError || e));
    });
}

describe('Kerberos', function () {
  const sandbox = sinon.createSandbox();

  beforeEach(function () {
    sandbox.spy(dns);
  });

  afterEach(function () {
    sandbox.restore();
  });

  if (process.env.MONGODB_URI == null) {
    console.error('skipping Kerberos tests, MONGODB_URI environment variable is not defined');
    return;
  }
  let krb5Uri = process.env.MONGODB_URI;
  const parts = krb5Uri.split('@', 2);
  const host = parts[1].split('/')[0];

  if (!process.env.KRB5_PRINCIPAL) {
    console.error('skipping Kerberos tests, KRB5_PRINCIPAL environment variable is not defined');
    return;
  }

  if (process.platform === 'win32') {
    console.error('Win32 run detected');
    if (process.env.LDAPTEST_PASSWORD == null) {
      throw new Error('The env parameter LDAPTEST_PASSWORD must be set');
    }
    krb5Uri = `${parts[0]}:${process.env.LDAPTEST_PASSWORD}@${parts[1]}`;
  }

  it('should authenticate with original uri', function (done) {
    const client = new MongoClient(krb5Uri);
    client.connect(function (err, client) {
      expect(err).to.not.exist;
      verifyKerberosAuthentication(client, done);
    });
  });

  it('validate that gssapiCanonicalizeHostName can be passed in', function (done) {
    if (process.platform === 'darwin') {
      this.test.skipReason = 'DNS does not resolve with proper CNAME record on evergreen MacOS';
      this.skip();
    }
    const client = new MongoClient(
      `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,gssapiCanonicalizeHostName:true&maxPoolSize=1`
    );
    client.connect(function (err, client) {
      if (err) return done(err);
      expect(dns.resolveCname).to.be.calledOnceWith(host);
      verifyKerberosAuthentication(client, done);
    });
  });

  context('when passing in CANONICALIZE_HOST_NAME', function () {
    beforeEach(function () {
      if (process.platform === 'darwin') {
        this.currentTest.skipReason =
          'DNS does not resolve with proper CNAME record on evergreen MacOS';
        this.skip();
      }
    });

    context('when the value is forward', function () {
      it('authenticates with a forward cname lookup', function (done) {
        const client = new MongoClient(
          `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:forward&maxPoolSize=1`
        );
        client.connect(function (err, client) {
          if (err) return done(err);
          expect(dns.resolveCname).to.be.calledOnceWith(host);
          verifyKerberosAuthentication(client, done);
        });
      });
    });

    for (const option of [false, 'none']) {
      context(`when the value is ${option}`, function () {
        it('authenticates with no dns lookups', function (done) {
          const client = new MongoClient(
            `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:${option}&maxPoolSize=1`
          );
          client.connect(function (err, client) {
            if (err) return done(err);
            expect(dns.resolveCname).to.not.be.called;
            // 2 calls when establishing connection - expect no third call.
            expect(dns.lookup).to.be.calledTwice;
            verifyKerberosAuthentication(client, done);
          });
        });
      });
    }

    for (const option of [true, 'forwardAndReverse']) {
      context(`when the value is ${option}`, function () {
        context('when the reverse lookup succeeds', function () {
          const resolveStub = (address, callback) => {
            callback(null, [host]);
          };

          beforeEach(function () {
            dns.resolvePtr.restore();
            sinon.stub(dns, 'resolvePtr').callsFake(resolveStub);
          });

          it('authenticates with a forward dns lookup and a reverse ptr lookup', function (done) {
            const client = new MongoClient(
              `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:${option}&maxPoolSize=1`
            );
            client.connect(function (err, client) {
              if (err) return done(err);
              // 2 calls to establish connection, 1 call in canonicalization.
              expect(dns.lookup).to.be.calledThrice;
              expect(dns.resolvePtr).to.be.calledOnce;
              verifyKerberosAuthentication(client, done);
            });
          });
        });

        context('when the reverse lookup is empty', function () {
          const resolveStub = (address, callback) => {
            callback(null, []);
          };

          beforeEach(function () {
            dns.resolvePtr.restore();
            sinon.stub(dns, 'resolvePtr').callsFake(resolveStub);
          });

          it('authenticates with a fallback cname lookup', function (done) {
            const client = new MongoClient(
              `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:${option}&maxPoolSize=1`
            );
            client.connect(function (err, client) {
              if (err) return done(err);
              // 2 calls to establish connection, 1 call in canonicalization.
              expect(dns.lookup).to.be.calledThrice;
              // This fails.
              expect(dns.resolvePtr).to.be.calledOnce;
              // Expect the fallback to the host name.
              expect(dns.resolveCname).to.not.be.called;
              verifyKerberosAuthentication(client, done);
            });
          });
        });

        context('when the reverse lookup fails', function () {
          const resolveStub = (address, callback) => {
            callback(new Error('not found'), null);
          };

          beforeEach(function () {
            dns.resolvePtr.restore();
            sinon.stub(dns, 'resolvePtr').callsFake(resolveStub);
          });

          it('authenticates with a fallback cname lookup', function (done) {
            const client = new MongoClient(
              `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:${option}&maxPoolSize=1`
            );
            client.connect(function (err, client) {
              if (err) return done(err);
              // 2 calls to establish connection, 1 call in canonicalization.
              expect(dns.lookup).to.be.calledThrice;
              // This fails.
              expect(dns.resolvePtr).to.be.calledOnce;
              // Expect the fallback to be called.
              expect(dns.resolveCname).to.be.calledOnceWith(host);
              verifyKerberosAuthentication(client, done);
            });
          });
        });

        context('when the cname lookup fails', function () {
          const resolveStub = (address, callback) => {
            callback(new Error('not found'), null);
          };

          beforeEach(function () {
            dns.resolveCname.restore();
            sinon.stub(dns, 'resolveCname').callsFake(resolveStub);
          });

          it('authenticates with a fallback host name', function (done) {
            const client = new MongoClient(
              `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:${option}&maxPoolSize=1`
            );
            client.connect(function (err, client) {
              if (err) return done(err);
              // 2 calls to establish connection, 1 call in canonicalization.
              expect(dns.lookup).to.be.calledThrice;
              // This fails.
              expect(dns.resolvePtr).to.be.calledOnce;
              // Expect the fallback to be called.
              expect(dns.resolveCname).to.be.calledOnceWith(host);
              verifyKerberosAuthentication(client, done);
            });
          });
        });

        context('when the cname lookup is empty', function () {
          const resolveStub = (address, callback) => {
            callback(null, []);
          };

          beforeEach(function () {
            dns.resolveCname.restore();
            sinon.stub(dns, 'resolveCname').callsFake(resolveStub);
          });

          it('authenticates with a fallback host name', function (done) {
            const client = new MongoClient(
              `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:${option}&maxPoolSize=1`
            );
            client.connect(function (err, client) {
              if (err) return done(err);
              // 2 calls to establish connection, 1 call in canonicalization.
              expect(dns.lookup).to.be.calledThrice;
              // This fails.
              expect(dns.resolvePtr).to.be.calledOnce;
              // Expect the fallback to be called.
              expect(dns.resolveCname).to.be.calledOnceWith(host);
              verifyKerberosAuthentication(client, done);
            });
          });
        });
      });
    }
  });

  // Unskip this test when a proper setup is available - see NODE-3060
  it.skip('validate that SERVICE_REALM and CANONICALIZE_HOST_NAME can be passed in', function (done) {
    const client = new MongoClient(
      `${krb5Uri}&authMechanismProperties=SERVICE_NAME:mongodb,CANONICALIZE_HOST_NAME:false,SERVICE_REALM:windows&maxPoolSize=1`
    );
    client.connect(function (err, client) {
      expect(err).to.not.exist;
      verifyKerberosAuthentication(client, done);
    });
  });

  context('when passing SERVICE_HOST as an auth mech option', function () {
    context('when the SERVICE_HOST is invalid', function () {
      const client = new MongoClient(`${krb5Uri}&maxPoolSize=1`, {
        authMechanismProperties: {
          SERVICE_HOST: 'example.com'
        }
      });

      it('fails to authenticate', async function () {
        let expectedError;
        await client.connect().catch(e => {
          expectedError = e;
        });
        if (!expectedError) {
          expect.fail('Expected connect with invalid SERVICE_HOST to fail');
        }
        expect(expectedError.message).to.match(/GSS failure|UNKNOWN_SERVER/);
      });
    });

    context('when the SERVICE_HOST is valid', function () {
      const client = new MongoClient(`${krb5Uri}&maxPoolSize=1`, {
        authMechanismProperties: {
          SERVICE_HOST: 'ldaptest.10gen.cc'
        }
      });

      it('authenticates', function (done) {
        client.connect(function (err, client) {
          expect(err).to.not.exist;
          verifyKerberosAuthentication(client, done);
        });
      });
    });
  });

  describe('should use the SERVICE_NAME property', function () {
    it('as an option handed to the MongoClient', function (done) {
      const client = new MongoClient(`${krb5Uri}&maxPoolSize=1`, {
        authMechanismProperties: {
          SERVICE_NAME: 'alternate'
        }
      });
      client.connect(function (err) {
        expect(err).to.exist;
        expect(err.message).to.match(
          /(Error from KDC: LOOKING_UP_SERVER)|(not found in Kerberos database)|(UNKNOWN_SERVER)/
        );
        done();
      });
    });

    it('as part of the query string parameters', function (done) {
      const client = new MongoClient(
        `${krb5Uri}&authMechanismProperties=SERVICE_NAME:alternate&maxPoolSize=1`
      );
      client.connect(function (err) {
        expect(err).to.exist;
        expect(err.message).to.match(
          /(Error from KDC: LOOKING_UP_SERVER)|(not found in Kerberos database)|(UNKNOWN_SERVER)/
        );
        done();
      });
    });
  });

  it('should fail to authenticate with bad credentials', function (done) {
    const client = new MongoClient(
      krb5Uri.replace(encodeURIComponent(process.env.KRB5_PRINCIPAL), 'bad%40creds.cc')
    );
    client.connect(function (err) {
      expect(err).to.exist;
      expect(err.message).to.match(/Authentication failed/);
      done();
    });
  });
});