Repository: jborean93/smbprotocol (language: python)

Issue:
Tests for copymode throwing NotImplementedError failing on macOS
```
_______________ test_copymode_local_to_local_symlink_dont_follow _______________

tmpdir = local('/private/tmp/nix-build-python3.9-smbprotocol-1.5.1.drv-0/pytest-of-veprbl/pytest-0/test_copymode_local_to_local_s1')

    @pytest.mark.skipif((os.name == 'nt' and sys.version_info[0] < 3) or
                        (sys.version_info[0] == 3 and sys.version_info[1] == 5),
                        reason="Python 3.5 errors out on os.chmod(follow_symlinks=False)")
    def test_copymode_local_to_local_symlink_dont_follow(tmpdir):
        test_dir = tmpdir.mkdir('test')
        src_filename = "%s\\source.txt" % test_dir
        dst_filename = "%s\\target.txt" % test_dir
    
        with open(src_filename, mode='w') as fd:
            fd.write(u"content")
        os.chmod(src_filename, stat.S_IREAD)
    
        with open(dst_filename, mode='w') as fd:
            fd.write(u"content")
    
        src_link = "%s\\source-link.txt" % test_dir
        dst_link = "%s\\target-link.txt" % test_dir
    
        os.symlink(src_filename, src_link)
        os.symlink(dst_filename, dst_link)
    
        expected = "chmod: follow_symlinks unavailable on this platform"
        with pytest.raises(NotImplementedError, match=re.escape(expected)):
>           copymode(src_link, dst_link, follow_symlinks=False)
E           Failed: DID NOT RAISE <class 'NotImplementedError'>

tests/test_smbclient_shutil.py:605: Failed
____________ test_copystat_local_to_local_symlink_dont_follow_fail _____________

tmpdir = local('/private/tmp/nix-build-python3.9-smbprotocol-1.5.1.drv-0/pytest-of-veprbl/pytest-0/test_copystat_local_to_local_s1')

    @pytest.mark.skipif((os.name == 'nt' and sys.version_info[0] < 3) or
                        (sys.version_info[0] == 3 and sys.version_info[1] == 5),
                        reason="Python 3.5 errors out on os.chmod(follow_symlinks=False)")
    def test_copystat_local_to_local_symlink_dont_follow_fail(tmpdir):
        test_dir = tmpdir.mkdir('test')
        src_filename = "%s\\source.txt" % test_dir
        dst_filename = "%s\\target.txt" % test_dir
    
        with open(src_filename, mode='w') as fd:
            fd.write(u"content")
        os.chmod(src_filename, stat.S_IREAD)
    
        with open(dst_filename, mode='w') as fd:
            fd.write(u"content")
    
        src_link = "%s\\source-link.txt" % test_dir
        dst_link = "%s\\target-link.txt" % test_dir
    
        os.symlink(src_filename, src_link)
        os.symlink(dst_filename, dst_link)
    
        expected = "follow_symlinks unavailable on this platform"
        with pytest.raises(NotImplementedError, match=re.escape(expected)):
>           copystat(src_link, dst_link, follow_symlinks=False)
E           Failed: DID NOT RAISE <class 'NotImplementedError'>
```


Discussion / hints:
Thanks for the report.

I guess that the change for this test should be

```diff
-@pytest.mark.skipif((os.name == 'nt' and sys.version_info[0] < 3) or
+@pytest.mark.skipif((os.name != 'posix' and sys.version_info[0] < 3) or
```

but at the same time, the automated/CI Azure Devops tests should be updated to be also executed on macOS.

From what I can see, the current configuration file only runs the tests on Linux and Windows

https://github.com/jborean93/smbprotocol/blob/master/azure-pipelines.yml

smbprotocol might work on macOS, but without continuous tests on macOS I think that it macOS can be considered as unofficially supported.

@jborean93 are  you interested into macOS ? Do you prefer to run macOS  tests via Azure Pipelines or GitHub Actions?
I can help with a PR.
I prefer GitHub Actions as the logs are easier to read...and you don't need extra access and permissions to Azure to re-run a job.
But Azure Pipelines is super nice as with flaky tests it allows to re-run only the failed jobs.
But I think that a project should not have flaky tests... so that would not be an issue with GitHub Actions :)

Probably easiest to just add macOS to the AZP matrix to avoid having 2 places where CI runs. I originally worked on macOS on my dev box but that's no longer. I'm fairly confident nothing is actually broken on macOS, just some tests may not work.

Fix patch:
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 7375a3bb..20caac4d 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,3 +1,10 @@
+#
+# Docs for YAML schema
+# https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema
+#
+# Available MS hosted OSes
+# https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted
+#
 trigger:
   branches:
     include:
@@ -107,6 +114,49 @@ stages:
       continueOnError: true
       timeoutInMinutes: 5
 
+
+  - job: Test_MacOs
+    pool:
+      vmImage: macOS-10.15
+
+    steps:
+    - task: UsePythonVersion@0
+      inputs:
+        versionSpec: 3.9
+
+    - script: |
+        echo "Installing baseline pip packages"
+        python -m pip install --upgrade pip setuptools wheel coverage -c tests/constraints.txt
+
+        echo "Installing test requirements"
+        python -m pip install -r requirements-test.txt -c tests/constraints.txt
+
+        echo "Installing package"
+        python -m pip install . -c tests/constraints.txt
+      displayName: Install
+
+    - script: |
+        pytest -v --junitxml junit/test-results.xml --cov smbclient --cov smbprotocol --cov-report xml --cov-report term-missing
+      displayName: Test
+
+    - task: PublishTestResults@2
+      inputs:
+        testResultsFiles: '**/test-*.xml'
+        testRunTitle: $(Agent.OS) - $(Build.BuildNumber) - Python $(python.version)
+      displayName: Publish test results
+      condition: succeededOrFailed()
+
+    - task: PublishCodeCoverageResults@1
+      inputs:
+        codeCoverageTool: Cobertura
+        summaryFileLocation: $(System.DefaultWorkingDirectory)/**/coverage.xml
+
+    - script: |
+        bash <(curl -s https://codecov.io/bash)
+      displayName: Upload to codecov.io
+      continueOnError: true
+      timeoutInMinutes: 5
+
   - job: Test_Windows
     variables:
       smb_share: share


Test patch:
diff --git a/tests/test_smbclient_shutil.py b/tests/test_smbclient_shutil.py
index a2775358..71b32fda 100644
--- a/tests/test_smbclient_shutil.py
+++ b/tests/test_smbclient_shutil.py
@@ -605,6 +605,8 @@ def test_copymode_local_to_local_symlink_follow(tmpdir):
     assert stat.S_IMODE(actual_link) & stat.S_IWRITE == stat.S_IWRITE
 
 
+@pytest.mark.skipif(sys.platform.startswith('darwin'),
+                    reason="On macOS os.chmod supports symlinks.")
 def test_copymode_local_to_local_symlink_dont_follow(tmpdir):
     test_dir = tmpdir.mkdir('test')
     src_filename = "%s\\source.txt" % test_dir
@@ -858,6 +860,8 @@ def test_copystat_local_to_local_symlink_follow(tmpdir):
     assert stat.S_IMODE(actual_link.st_mode) & stat.S_IWRITE == stat.S_IWRITE
 
 
+@pytest.mark.skipif(sys.platform.startswith('darwin'),
+                    reason="On macOS os.chmod supports symlinks.")
 def test_copystat_local_to_local_symlink_dont_follow_fail(tmpdir):
     test_dir = tmpdir.mkdir('test')
     src_filename = "%s\\source.txt" % test_dir